Python sqlite3“数据库已锁定”不会因重试而消失

Python sqlite3“数据库已锁定”不会因重试而消失,python,sqlite,Python,Sqlite,我有一个sqlite3数据库,由几个线程3-4访问。我知道sqlite3在并发性方面的一般限制,但我相信这不是问题所在 所有线程都从该数据库读取和写入。每当我进行写操作时,我都有以下结构: try: Cursor.execute(q, params) Connection.commit() except sqlite3.IntegrityError: N

我有一个sqlite3数据库,由几个线程3-4访问。我知道sqlite3在并发性方面的一般限制,但我相信这不是问题所在

所有线程都从该数据库读取和写入。每当我进行写操作时,我都有以下结构:

            try:
                Cursor.execute(q, params)
                Connection.commit()
            except sqlite3.IntegrityError:
                Notify
            except sqlite3.OperationalError:
                print sys.exc_info()
                print("DATABASE LOCKED; sleeping for 3 seconds and trying again")
                time.sleep(3)
                Retry
在一些运行中,我甚至不会碰到这个块,但是当我碰到这个块时,它永远不会出现。我不断地重试,但是我不断地从exc_info中得到“database is locked”错误。如果我正确理解读写器锁的用法,那么一定的等待时间应该有助于解决争用问题。这听起来像是死锁,但我的代码中没有使用任何事务,而且每个SELECT或INSERT都是一次性的。但是,有些线程在执行操作时保持相同的连接,这些操作包括选择、插入和其他修改器


如果你能给它加上阴影,我会喜欢它,除了使用不同的数据库引擎之外,还有其他修复方法。

每次尝试写入数据库时,Sqlite都会锁定整个数据库。有没有可能你的一个帖子一直在写?是只有一个线程命中了数据库锁,还是所有线程都购买了其中一个?

这里有一个不那么优雅的临时修复方法:在写操作周围使用外部独占锁,而不是依赖内部sqlite锁。问题中的上述块基本上是用一个系统范围的锁包装的,每个线程在写入之前都必须获取该锁。由于sqlite3在编写时会锁定整个数据库,我希望这不会增加更多的开销


另一方面,读取可以在不获取锁的情况下继续进行,我认为这可能适用于限制较少的读取器锁sqlite3需求

在一个每天约有200名用户的网站上,我也遭受了这种痛苦,该网站的浏览量可能达到1000次。重试并没有起到任何作用,我最终将重试次数增加到了100次,中间有短暂的睡眠。我不记得它是哪个版本的SQLite,但我学到了一个教训:如果您想对SQLite数据库进行可靠的并发写入,那么最好使用其他数据库,如MySQL或PostgreSQL


即使您解决了OperationalError-s的问题,这仍然有效,因为对SQLite文件的并发写入最终将永远破坏性能。

Hi tamulj,没有一个线程一直在基于事件处理程序写入线程,一次不超过几行。您能构建一个非常小的独立测试用例来演示这个问题吗?如果我们有可执行代码,并且可以看到整个过程,那就容易多了。嗨,达斯汀,事实可能证明这很难,因为即使有更大的代码库,我也很难复制它。我主要想知道这是否是一个常见问题,以及sqlite3中是否存在已知的死锁问题。我将发布我的不那么优雅的修复暂时。