SQLite与OpenAFS锁定兼容吗?

时间:2011-03-29 05:40:53

标签: sqlite locking posix openafs

我希望许多联网计算机上的许多进程同时通过OpenAFS 1.4.12.1访问同一个SQLite数据库。写入很少,因此SQLite的单写设计应该不是问题。

我想知道这是否可行。我无法找到两个关键信息:

SQLite documentation表示“SQLite使用POSIX顾问锁在Unix上实现锁定”。它还警告说“你最好的防御就是不要将SQLite用于网络文件系统上的文件”。但是,它似乎没有指定SQLite是仅使用整个文件锁定,还是它还使用字节范围锁定。

我也无法找到OpenAFS 1.4.12.1支持哪种类型的锁定。遗憾的是,这unofficial source from 1998是我能找到的最佳来源。当时,支持整个文件锁定,但不支持字节范围锁定。

官方文档仅显示this page,尽管它的友好标题实际上没有说明最新的OpenAFS是否支持POSIX字节范围建议锁定。

编辑: 这有可能吗?如果是这样,是否需要任何编译时SQLite标志?

1 个答案:

答案 0 :(得分:5)

我已经使用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()。我不确定这是否会正常工作,因为即使使用普通的flock(),OpenAFS也有很长的历史记录([1][2])锁定问题,但是直到你测试一下。

  • 使用OpenAFS用户空间为SQLite实现自己的OpenAFS VFS,而不是通过内核。

  • 试试其他网络文件系统。

无论您做什么,如果以任何方式涉及SQLite3和共享数据库文件,您都必须执行大量测试。

编辑:

评论者建议使用dotlock文件机制。我没有深入研究OpenAFS源代码,但乍一看似乎支持创建SQLite使用的dotlock文件的open(O_CREAT|O_EXCL)方法。如果它按预期工作,那么如果强制它使用dotlock方法,那么SQLite可能确实可以用于OpenAFS。

也就是说,dotlocks足以解决常规本地文件系统的问题,而不会将网络文件系统的复杂性引入混合中 - 这就是为什么我首先没有提出它的原因。