我一直在使用SQLite很長一段時間,並有處理一些鎖定問題的「財富」。我很確定SQLite默認情況下在Unix文件系統上使用字節範圍鎖。
更確切地說,它包含一些替代鎖定方法的代碼(例如使用flock()
和dotlock-style整個文件鎖)。當使用SQLITE_ENABLE_LOCKING_STYLE
option進行編譯時,它會嘗試自動檢測底層文件系統的正確鎖定方法。
自動檢測代碼包含一些硬編碼的情況(例如「ufs」,「nfs」和「smbfs」),它們都不是AFS。如果沒有硬編碼的大小寫匹配,SQLite將嘗試使用fcntl()
獲取文件的字節範圍鎖定。然後假設如果fcntl()
調用成功,則字節範圍鎖定可用。
這裏是OpenAFS進來使事情有趣。顯然([1],[2],[3])OpenAFS有一個long躺在用戶空間應用程序關於字節範圍鎖的歷史。從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上,它可能更糟糕:它使用內核基礎結構在相同系統的進程中提供字節範圍鎖。這意味着應用程序不能只分叉一個新進程並測試鎖定機制 - 字節範圍鎖定似乎工作正常,但卻無法保護遠程進程中的文件。
簡而言之:不能在OpenAFS中可靠地使用未經修改的SQLite。大多數其他網絡文件系統也有問題,因此建議完全避免網絡文件系統。
幾個可能的變通沒有特定的順序:
使用適當的DBMS,例如PostgreSQL。如果有可能做到這一點,那麼從長遠來看,你會變得更好。
如果您的應用程序實現了您自己的服務器,如果一個成熟的DBMS過度殺傷。
在OpenAFS上將SQLite源代碼修改爲默認爲flock()
。我不確定這是否可以正常工作,因爲OpenAFS的歷史悠久([1],[2]),即使使用普通的舊版本flock()
也是如此,但在測試之前您不會知道。
使用OpenAFS用戶空間實現自己的OpenAFS VFS for SQLite,而不是通過內核。
試試你的運氣與另一個網絡文件系統。
無論你做什麼,你將不得不執行廣泛的測試,如果以任何方式涉及SQLite3和共享數據庫文件。
編輯:
評論者建議使用點鎖文件機制。我沒有深入研究OpenAFS源代碼,但乍一看似乎支持創建SQLite使用的dotlock文件的open(O_CREAT|O_EXCL)
方法。如果它按照它的設想工作,那麼SQLite可能確實可以與OpenAFS一起使用,如果您強制它使用點鎖方法。
這就是說,在沒有將網絡文件系統的複雜性引入混合中的情況下,在常規的本地文件系統中,dotlocks已經足夠了 - 這就是爲什麼我沒有首先提出它的原因。
+1確實。但是,假設AFS提供了原子文件創建,不會出現點鎖嗎? – janneb 2011-04-04 14:23:17
@janneb:我檢查了OpenAFS源碼w.r.t. dotlocks。結果是令人鼓舞的 - 或者因爲任何涉及到斑點的事情都是令人鼓舞的。 – thkala 2011-04-04 16:22:50