为什么 sqlite3 不能在 Amazon Elastic File System 上运行?

Why does sqlite3 not work on Amazon Elastic File System?

当我尝试在 EFS 目录上使用 sqlite3 创建基础时,这会导致错误:

$ sqlite3 foo.db SQLite version 3.7.17 2013-05-20 00:56:22 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> .log stderr sqlite> CREATE TABLE foo (int bar); Error: disk I/O error

有问题的 Sqlite3 数据库应该只是故事元数据,并且不会经常更新。不需要并发访问。但是,要求如果创建数据库的进程挂掉,该进程可以在不同的主机上重新启动,并在前一个实例退出的地方继续。

Amazon 声称 EFS 是 "file system that [is] accessible to Amazon EC2 instances via a file system interface (using standard operating system file I/O APIs) and that support full file system access semantics (such as strong consistency and file locking)." 因此,我假设它适合手头的任务。

/etc/fstab 中的挂载选项是:

eu-west-1a.fs-ID.efs.eu-west-1.amazonaws.com:/ /efs nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0

我明白 it is often generally discouraged to put databases on NFS。但是,我相信,考虑到 Amazon 和 SQLite 使用的语言,开发人员会继续尝试。

更新(2017 年 3 月 6 日):

EFS 现在支持 NFS v4.1 锁升级和降级:

https://aws.amazon.com/about-aws/whats-new/2017/03/amazon-elastic-file-system-amazon-efs-now-supports-nfsv4-lock-upgrading-and-downgrading/

来自文档:

Lock upgrades and downgrades: Amazon EFS returns NFS4ERR_LOCK_NOTSUPP if the client attempts to upgrade or downgrade an existing lock.

Note

Because lock upgrades and downgrades are not supported, use cases that require this feature, such as those using SQLite or IPython, are also not supported in Amazon EFS.

参见:

http://docs.aws.amazon.com/efs/latest/ug/efs-ug.pdf

还有:

http://docs.aws.amazon.com/efs/latest/ug/nfs4-unsupported-features.html

默认情况下,sqlite 在 "unix" VFS 上运行,它使用不受 Amazon EFS 锁升级支持的。但是,如果将 VFS 更改为 "unix-excl",则可以在 Amazon EFS 上使用 sqlite 数据库,它使用独占文件锁并且不需要升级。

有几种方法可以指定 VFS。如果您使用命令行,只需添加“-vfs unix-excl”选项:

ubuntu@ip-1-1-1-1 /efs> sqlcipher foo.db -vfs unix-excl
SQLCipher version 3.8.10.2 2015-05-20 18:17:19
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> CREATE TABLE foo (int bar);
sqlite> .exit

如果使用from API,则需要在调用open函数之前注册VFS:

sqlite3_vfs_register(sqlite3_vfs_find("unix-excl"), 1);
sqlite3_open("foo.db", &db);

如果使用 PHP PDO,那么你就卡住了,除非你愿意重新编译 pdo_sqlite PHP 扩展。