2010-01-12 147 views
4

我有一个sqlite3数据库可以被几个线程(3-4)访问。我知道sqlite3关于并发性的一般限制,如http://www.sqlite.org/faq.html#q6所述,但我相信这不是问题。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 

在某些运行时,我甚至不会打这个块,但是当我做,它永远不会出来的它(保持重试,但我一直如果我正确理解读写器锁的使用情况,一些等待可以帮助争用,这听起来像是死锁,但我没有在我的代码中使用任何事务,并且每个SELECT或INSERT都只是一个关闭,但是某些线程在执行操作时会保持相同的连接(其中包括SELECTS和INSERTS以及其他修饰符的混合)

如果可以,我会修改它为此遮光,还有修复它的方法(除了使用不同的数据库引擎)。

+0

你可以建立一个非常小的隔离测试用例来证明这个问题吗?如果我们有可执行代码并且可以看到整个事情,那会更容易。 – Dustin 2010-01-12 18:59:36

+0

嗨达斯汀,这可能实际上证明很难,因为即使有更大的代码库,我也很难再现它。我主要想知道这是否是一个常见问题,以及sqlite3中是否存在已知的死锁问题。我会暂时发布我不那么优雅的修补程序。 – BME 2010-01-13 14:26:52

回答

0

每当您尝试写入数据库时​​,Sqlite都会锁定整个数据库。有没有可能你的一个主题是不断写作的?只有一个线程触及数据库锁或全部购买其中一个?

+0

Hi tamulj, 没有一个线程在不停地写入(线程根据事件处理程序写入,一次只能写入几行)。 – BME 2010-01-12 18:26:33

0

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

在另一方面,读取,而不获取锁,我认为威力工作确定与限制较少的读者锁定sqlite3的需求出发。

0

我也遭受过这种情况,在一个每天有200个用户的网站上(这个网站的浏览量可能达到1000页)。重试只是没有帮助(我终于增加了他们的数量达到100,之间有短暂的睡眠)。我不记得它是哪个版本的SQLite,但我学到了一个教训:如果你想对SQLite数据库进行可靠的并发写入,那么你最好使用其他数据库,比如MySQL或PostgreSQL。

即使您使用OperationalError-s解决问题,也会出现问题,因为最终将并发写入SQLite文件会导致性能下降。