SQLite3与多进程
我发现,当我在多进程环境中使用sqlite3时,它并不是特别可靠。每个进程都试图往同一个数据库里写数据,这就导致多个线程在使用同一个连接。我尝试过使用check_same_thread=False这个选项,但插入的数据数量却很随机:有时候能插入所有数据,有时候却不能。我是不是应该只让函数的某些部分并行处理(比如从网上获取数据),把它们的输出放到一个列表里,然后一起放进数据库?还是说有其他可靠的方法来处理sqlite的多连接?
4 个回答
我最近在做一个很相似的事情:
- 有多个进程(对我来说是一个处理池,里面有4到32个工作者)
- 每个工作者会做一些事情,包括从网上获取信息(我用的是Alchemy API)
- 每个进程都打开自己的sqlite3连接,连接到同一个文件,每个进程在获取下一个任务之前会先添加一条记录
起初我以为我遇到的问题和你一样,后来我发现是因为从网上获取信息时出现了重叠和冲突的问题。因为我就在那儿,所以我对sqlite和多进程进行了压力测试,发现我可以运行很多工作者,它们都能连接并向同一个sqlite文件添加数据,而且在我只放入测试数据的时候,系统非常稳定。
现在我在想你提到的“(从网上获取数据)”这句话——也许你可以试着用一些假数据来替代这些数据获取,看看是不是sqlite3连接导致了你的问题。至少在我测试的情况下(现在在另一个窗口运行),我发现多个进程能够通过各自的连接顺利添加数据,但你的描述正好和我在两个进程同时访问网络API时遇到的问题一致(其实是个很奇怪的错误),有时得不到预期的数据,这样就会在数据库中留下空位。我的最终解决办法是在每个工作者中检测到这个失败后重试网络API调用(本来可以做得更优雅,但这是我个人的小项目)。
如果这对你的情况没有帮助,我很抱歉,因为没有代码很难知道你遇到的具体问题,但你的描述让我觉得你可能需要考虑更广泛一些。
首先,进程和线程是有区别的。进程是指多个独立的程序在运行,而线程则是在同一个程序内部的多个执行路径。
看起来你在这里讨论的是线程。使用SQLite在多线程环境中时,有几个注意事项你需要了解。SQLite的文档提到以下几点:
- 不要在多个线程中同时使用同一个数据库连接。
- 在某些操作系统上,数据库连接应该始终在创建它的同一个线程中使用。
想要了解更详细的信息,可以查看这里:SQLite是否线程安全?
sqlitedict:这是一个轻量级的工具,它把Python的sqlite3数据库进行了封装,让你可以像使用字典一样来操作数据库,并且支持多线程访问。