Google 的持久磁盘是否具有适当的读取器/写入器锁,以实现 SQLite 所需的并发访问(许多虚拟机从单个持久磁盘访问数据)?
SQLite 使用读写锁来控制对数据库的访问。[...] 但请谨慎使用:如果数据库文件保存在 NFS 文件系统上,此锁定机制可能无法正常工作。这是因为
fcntl()
许多 NFS 实现上的文件锁定功能已损坏。如果多个进程可能同时尝试访问文件,则应避免将 SQLite 数据库文件放在 NFS 上。
我真的很想知道 Google 的持久磁盘是否能正确锁定写入。我研究了 AWS 的 EFS,它没有合适的锁定系统来支持 SQLite。
答案1
更新(2019 年 8 月 30 日)
Canonical 的 Dqlite提供了一个分布式、高可用性的 SQLite,可能适合此用例。它开源在 Apache 2.0 下,用 C 语言编写,因此可以是 SQLite 的替代品。另请参阅HN 讨论了解更多背景信息。
先前的答案
根据您的评论,似乎 MySQL 和 Google Cloud SQL 不是一个选项,因为您的架构需要使用单个 SQLite 文件。
此外,根据 SQLite 文档,由于锁定问题,NFS 不是一个选项。
以下是一些可供考虑的其他选择。
替代分布式文件系统
除了 NFS 之外,您可能还想评估许多其他分布式文件系统,例如头孢,集群文件系统,橙色文件系统,虚拟文件系统等等。除了您自己的研究之外,还可以考虑联系 SQLite 用户或开发人员以获取指导和过去的经验。
使用 NFS,但强制一次只写入一个文件
NFS 问题似乎与锁定有关,这只需要写入:只要您可以保证一次只有一个进程锁定数据库以进行写入,其他几个进程就可以打开它进行读取,所以这应该没问题(请确认/验证是否是这种情况)。
因此,只要有外部方法可以确保单一写入者,你就可以使用 NFS。考虑使用分布式锁服务,例如Apache ZooKeeper,HashiCorp 领事或者CoreOS etcd用于锁定服务,您可以将 SQLite 存储在 NFS 上。
当然,这依赖于每个直接访问 SQLite 数据库的进程在不再需要写入时正确地关闭它,因此正确性很难执行,因为它依赖于所有软件的正确性和协作性。
轻量级 RPC 服务器
您提到您的架构(目前无法更改)依赖于 SQLite,但如果可以让它们调用 RPC 服务而不是直接打开文件,那么您可以将该服务器作为打开 SQLite 数据库的唯一点,并避免多个并发用户带来的锁定问题。但是,这意味着您必须更改所有客户端代码以调用 RPC 服务而不是直接打开 SQLite 数据库,这是一项不小的工作量。
结论
这些选择都不是微不足道的,需要付出努力。原因是:
与许多其他数据库管理系统不同,SQLite 不是客户端-服务器数据库引擎。相反,它嵌入到最终程序中。
因此,它不是适用于多个访问器的正确解决方案,因此需要大量的解决方法。
从长远来看,如果您必须做出重大更改才能继续维护此系统,您可能需要考虑迁移到 MySQL 或 Google Cloud SQL,而不是投资解决方法来继续使用 SQLite。
答案2
回复:使用 SQLite 进行多重访问:您链接到的常见问题解答说:
(5)多个应用程序或同一应用程序的多个实例是否可以同时访问单个数据库文件?
多个进程可以同时打开同一个数据库。多个进程可以同时执行 SELECT。但是,在任意时刻,只有一个进程可以对数据库进行更改。
这意味着您不应该将 SQLite 用作通用数据库,它旨在用作单个写入器的嵌入式数据库,尽管它也可以支持多个读取器。
回复:持久磁盘:请参阅我的答案有关 Stack Overflow 上的相关问题;简而言之,Google Compute Engine 上的持久磁盘可以通过以下方式安装:
- 读写单个实例
- 对多个实例只读
因此,您无法像您建议的那样将持久磁盘以读写模式共享给多个虚拟机。如果您想要一个共享数据库,yagmoth555评论中指出,您应该使用 SQL 数据库,例如 MySQL。
方便的是,谷歌云 SQL提供一个托管的 MySQL 实例,您可以从多个 VM 中使用它,因为它提供了适当的锁定以及备份、故障转移等。