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

问题描述 投票:0回答:3

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

OperationalError: (sqlite3.OperationalError) database is locked

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

python database sqlite gunicorn
3个回答
0
投票

是真的。 Sqlite 不是为这种应用程序而构建的。 Sqlite 真正适用于轻量级单线程、单实例应用程序。

Sqlite 连接是每个实例一个,如果您开始使用某种线程多路复用器(请参阅 https://www.sqlite.org/threadsafe.html),这是可能的,但麻烦多于它的价值.还有其他提供该功能的解决方案——看看 Postgresql 或 MySQL。这些数据库是开源的,有据可查,得到很好的支持,并支持您需要的那种并发性。


0
投票

我不确定 SQLAlchemy 如何处理连接,但如果您使用的是 Peewee ORM,那么解决方案非常简单。

当您的 Flask 应用程序发起请求时,您将打开一个到数据库的连接。然后当 Flask 发送响应时,您关闭数据库。

同样,在您的 cron 脚本中,当您开始使用数据库时打开一个连接,然后在该过程完成时关闭它。

您可能会考虑的另一件事是在 WAL 模式下使用 SQLite。这可以提高并发性。打开连接时,您可以使用 PRAGMA 查询设置日志模式。

有关详细信息,请参阅http://charlesleifer.com/blog/sqlite-small-fast-reliable-choose-any-three-/


0
投票

对于未来的读者——解决方案是双重的。

  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模式。这将使您能够在写入时读取数据库中已有的内容。

© www.soinside.com 2019 - 2024. All rights reserved.