sqlite3:避免“数据库锁定”冲突

4bbkushb  于 2023-04-12  发布在  SQLite
关注(0)|答案(3)|浏览(372)

我在一个cpu上并行运行两个python文件两者都使用相同的sqlite3数据库。我使用sqlalchemy处理sqlite3数据库,我的理解是sqlalchemy在一个应用程序中处理所有线程数据库问题。我的问题是如何处理来自两个不同应用程序的访问?我的两个程序中的一个是flask应用程序,另一个是cronjob,它会不时更新数据库。似乎即使是sqlite数据库上的只读任务也会锁定数据库,这意味着如果两个应用程序都想同时读或写,我会得到一个错误。

OperationalError: (sqlite3.OperationalError) database is locked

让我们假设我的cronjob应用程序每5分钟运行一次。我如何才能确保我的两个应用程序之间没有冲突?我可以在访问数据库之前将一些读取标志写入一个文件中,然后进行检查,但在我看来,应该有一个标准的方法来做到这一点?此外,我正在运行我的应用程序与gunicorn和原则上是可能有多个作业运行...所以我最终希望我的 flask 应用程序有2个以上的并行作业...谢谢卡尔

sr4lhrrt

sr4lhrrt1#

这是真的。Sqlite不是为这类应用程序构建的。Sqlite实际上是为轻量级单线程、单示例应用程序构建的。
Sqlite连接是每个示例一个,如果你开始进入某种线程多路复用器(参见https://www.sqlite.org/threadsafe.html),这是可能的,但它比它的价值更麻烦。还有其他提供该功能的解决方案-看看Postgresql或MySQL。这些数据库是开源的,有很好的文档,很好的支持,并支持你需要的并发类型。

mkh04yzy

mkh04yzy2#

我不确定SQLAlchemy是如何处理连接的,但是如果你使用的是PeeweeORM,那么解决方案就很简单了。
当你的Flask应用发起一个请求时,你将打开一个到DB的连接。然后当Flask发送响应时,你将关闭DB。
类似地,在cron脚本中,在开始使用DB时打开一个连接,然后在进程结束时关闭它。
另一件你可以考虑的事情是在WAL模式下使用SQLite。这可以提高并发性。当你打开你的连接时,你可以用一个PRAGMA查询来设置日志模式。
有关详细信息,请参阅http://charlesleifer.com/blog/sqlite-small-fast-reliable-choose-any-three-/

jmo0nnb3

jmo0nnb33#

对于未来的读者-解决方案是双重的。
1.您需要手动管理异常,等待并重试-类似于以下内容:

# retry
record = None
for i in range(3):
    try:
        my.sqlite.function()
        break # break out of the retry loop on success
    except sqlite3.OperationalError:
        time.sleep(0.01)
if not record:
    raise BigError("Bad!")

2:您需要启用WAL或Write Ahead Logging模式。这将使您能够在写入时读取数据库中已有的内容。

相关问题