具有两个python进程访问它的SQLite:一次阅读,一次写作


22

我正在开发一个包含两个组件的小型系统:一个从互联网资源中轮询数据,然后将其转换为sql数据以将其持久化在本地;第二个从本地实例读取该sql数据,并通过json和一个平稳的api提供服务。

我本来打算使用postgresql保留数据,但是由于应用程序将要存储的数据量非常小,无法提供服务,因此我认为这太过分了。SQLite是否可以胜任?我喜欢占用空间小的想法,并且不需要为此任务维护另一台sql服务器,但是我担心并发性。

似乎在启用预写日志记录的情况下,可以在不将任何进程锁定在数据库之外的情况下同时进行SQLite数据库的读写。

如果只有一个SQLite实例读取并且另一个写入,则单个SQLite实例能否维持两个并发进程对其进行访问?我开始编写代码,但想知道这是否是SQLite的错误应用。


3
@gnat酷。如果只有一个SQLite实例读取并且另一个写入,则单个SQLite实例能否维持两个并发进程对其进行访问?我开始编写代码,但想知道这是否是SQLite的错误应用。
bb

只是抬起头。在我以前的公司中,我们使用SQL(MS和Oracle Express)进行一些存储,我们总是觉得只要存储很少的数据,就不需要完整的数据库。因此,在其中一个版本中,我们决定完全按照您的工作来做。将这些产品替换为SQLite。我们有完全相同的事情,一个写程序可以将数据放置在磁盘上,并更新基于SQL的TOC和读进程(多个线程)来读取TOC以确定要检索的数据。这些天对SQLite一无所知,但是,我们遇到的很少的并发却成为了主要的痛苦……
DXM

...后面 我不记得所有的细节,但是我认为,当一个进程试图获得一个锁并且不能因为另一个进程正在读取而锁定时,它将休眠20至30秒,这会令人发疯。我们最终创建了一个负责SQLite访问的专用线程,然后我们拥有了我们的进程以及其中的所有线程,将它们的数据库请求序列化到那个线程。事后看来,我可能不会再选择SQLite。
DXM

1
@DXM感谢您的警告,但是经过一些测试之后,我还没有遇到任何类似的问题。我知道sqlite在2004年左右对第3版进行了大修,所以我想知道您的负面经历是否可以追溯到该时间之前。
bb 2013年

1
...自己,而不是依靠SQLite的锁定方案。我自己没有做这项工作,这是另一个团队,但我一直处于循环中,主要是为了提供反馈和好奇心。我还上网,做了一些独立的阅读,找到了原始作者的页面。从阅读中,我得到的印象是SQLite的发明者只是讨厌线程,并且不知道为什么有人会使用它们,因此a)并不是在设计DB时就考虑到了它们,b)锁/保护有点儿增加了/事后才入侵,因为有太多人要求这样做。
DXM 2013年

Answers:


25

您正在寻找文件锁定和并发文档。

SQLite进程使用一系列锁来处理并发。阅读时,几个进程可以获得一个SHARED锁。

写入的进程将需要获得RESERVED锁,并且仅当实际上必须将更改刷新到磁盘时,它才会移动到该PENDING状态。然后,任何读取过程都必须将文件解锁,之后写入过程便可以移至EXCLUSIVE写入实际数据库文件的位置。

由于写进程仅需要锁定数据库文件才能进行实际写操作(内存刷新,提交),因此仅由一个读程序和一个写程序组成的设置将表现良好。我希望它的设置与仅由一个进程完成所有读取和写入操作的设置一样好,甚至更好。

当您有多个进程频繁写入同一数据库时,SQLite不太适合,因为写入需要获得排他PENDING锁才能序列化更改。


感谢Martijn的详尽回答!我用一些脚本进行测试,似乎两个进程将愉快地同时读写单个sqlite实例。我正在执行并发读写请求,每隔1/100秒触发一次,但仍未收到锁定的数据库异常。奇怪的是,我唯一一次收到“数据库锁定”错误消息的时候是当手动尝试(使用sqlite3命令行客户端)尝试删除几行,而读取请求却以1/100秒的速度从我的脚本触发时。我想知道pysql是否会在发生此类错误后自动重试写入。
bb 2013年

10

只是想跟进,让大家知道实施成功。使用SQLite是一种真正的乐趣,而且一次只用一个进程编写它就不会遇到锁定问题……即使从辅助进程进行的并发读取非常快。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.