Я уже давно пользуюсь SQLite, и мне посчастливилось иметь дело с некоторыми проблемами с блокировками. Я вполне уверен, что SQLite по умолчанию использует блокировки байтового диапазона в файловых системах Unix.
Если быть более точным, он содержит код для нескольких альтернативных методов блокировки (например, с использованием flock()
и стиля блокировки точек блокировки всего файла). При компиляции с параметром SQLITE_ENABLE_LOCKING_STYLE
он пытается автоматически определить правильный метод блокировки для базовой файловой системы.
Код автоопределения содержит несколько жестко закодированных случаев (например, "ufs", "nfs" и "smbfs"), ни один из которых не является AFS. Если не найдено ни одного жестко заданного регистра, SQLite пытается получить блокировку диапазона байтов для файла, используя fcntl()
. Затем предполагается, что если вызов fcntl()
успешен, тогда доступны блокировки в байтовом диапазоне.
Здесь OpenAFS приходит, чтобы сделать вещи интересными . Очевидно ( [1] , [2] , [3] ) OpenAFS имеет длинную историю лжи приложениям пользовательского пространства о блокировки байтового диапазона. Из openafs-1.4.14
исходного кода:
/* next line makes byte range locks always succeed,
* even when they should block */
if (af->l_whence != 0 || af->l_start != 0 || af->l_len != 0) {
DoLockWarning();
afs_PutFakeStat(&fakestate);
return 0;
}
Одним словом: Ой!
Это позволяет блокировкам байтового диапазона преуспеть, несмотря ни на что. В Linux это, возможно, еще хуже: он использует инфраструктуру ядра для обеспечения блокировок диапазона байтов среди процессов одной и той же системы . Это означает, что приложение не может просто разветвить новый процесс и протестировать механизм блокировки - блокировки в байтовом диапазоне будут работать нормально, но при этом не смогут защитить файл от удаленных процессов.
Короче говоря: вы не можете использовать немодифицированный SQLite надежно с OpenAFS. У большинства других сетевых файловых систем также есть проблемы, поэтому рекомендуется полностью избегать сетевых файловых систем.
Несколько возможных обходных путей в произвольном порядке:
Используйте правильную СУБД, такую как PostgreSQL . Если это возможно, в конечном итоге вам будет лучше.
Внедрите свой собственный сервер для своего приложения, если полноценная СУБД излишня.
Измените исходный код SQLite по умолчанию на flock()
в OpenAFS. Я не уверен, что это будет работать должным образом, поскольку OpenAFS имеет долгую историю ( [1] , [2] ) проблем блокировки даже с простой старой flock()
, но вы не узнаете, пока не протестируете его.
Реализуйте свою собственную VFS OpenAFS для SQLite, используя пользовательское пространство OpenAFS, а не проходя через ядро.
Испытайте удачу с другой сетевой файловой системой.
Что бы вы ни делали, вам придется проводить расширенное тестирование, если оно каким-либо образом связано с SQLite3 и файлом общей базы данных.
EDIT:
Комментатор предложил использовать механизм файлов точек блокировки. Я не слишком углублялся в исходный код OpenAFS, но на первый взгляд кажется, что он поддерживает метод open(O_CREAT|O_EXCL)
для создания файлов точек блокировки, который использует SQLite. Если это работает так, как предполагалось, SQLite действительно может быть использован с OpenAFS, если вы заставите его использовать метод dotlock.
Тем не менее, точечные блокировки являются достаточной проблемой на обычных локальных файловых системах, не привнося в сложность тонкости сетевой файловой системы - вот почему я не предложил это в первую очередь.