5

我想让许多联网计算机上的许多进程同时通过 OpenAFS 1.4.12.1 访问同一个 SQLite 数据库。写入将不频繁,因此 SQLite 的单写入设计应该不成问题。

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

SQLite 文档指出“SQLite 使用 POSIX 咨询锁来实现 Unix 上的锁定” 。它还警告说“你最好的防御是不要将 SQLite 用于网络文件系统上的文件”。但是,它似乎没有指定 SQLite 是否仅使用整个文件锁定,或者它是否也使用字节范围锁定。

我也很难找出 OpenAFS 1.4.12.1 支持的锁定类型。不幸的是,这个1998 年的非官方来源是我能找到的最好的来源。那时,支持整个文件锁定,但不支持字节范围锁定。

官方文档只出现了这个页面,尽管它的标题很友好,但实际上并没有说明最新的 OpenAFS 是否支持 POSIX 字节范围咨询锁定。

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

4

1 回答 1

5

我使用 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 上,可能会更糟:它使用内核基础设施在同一系统的进程之间提供字节范围锁。这意味着应用程序不能仅仅派生一个新进程并测试锁定机制 - 字节范围锁定似乎工作正常,但在保护文件免受远程进程影响方面却非常失败。

简而言之:你不能在 OpenAFS 中可靠地使用未经修改的 SQLite。大多数其他网络文件系统也存在问题,因此建议完全避免使用网络文件系统。

一些可能的解决方法,没有特定的顺序:

  • 使用适当的 DBMS,例如PostgreSQL。如果可以做到这一点,从长远来看,你会过得更好。

  • 如果一个成熟的 DBMS 太过分的话,请为您的应用程序实现您自己的服务器。

  • 将 SQLite 源代码修改为默认flock()在 OpenAFS 上。我不确定这是否能正常工作,因为 OpenAFS 有很长的锁定问题历史([1][2]),即使是 plain-old 也是如此flock(),但在你测试之前你不会知道。

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

  • 用另一个网络文件系统试试你的运气。

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

编辑:

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

也就是说,点锁在常规本地文件系统上就足够了,而不会将网络文件系统的复杂性引入其中——这就是我一开始没有建议它的原因。

于 2011-04-04T14:01:25.610 回答