当从不同线程中删除同一个表中的记录时,Sqlite处于死锁状态

时间:2014-07-01 20:42:58

标签: c++ database multithreading sqlite

我们在应用程序中使用sqlite 3.7.14.1代码。最近,我们在从表中删除记录时看到了死锁状态。删除是从两个不同的线程完成并作用于同一个表。

Sqlite在WAL模式下配置。所有线程都打开自己与数据库的共享连接。该应用程序符合SQLITE_THREADSAFE = 1和SQLITE_ENABLE_MEMORY_MANAGEMENT。

m_init = sqlite3_open_v2(
            m_dbfilename.toUtf8().data(),                                                                   /* Database filename (UTF-8) */
            &m_dbHandler,                                                                                   /* OUT: SQLite db handle */
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_SHAREDCACHE,    /* Flags */
            NULL                                                                                             /* Name of VFS module to use */
            );

多个线程中的记录的所有更新,插入和删除都发生在事务中。更新/插入语句完全没有任何死锁。但是当两个或多个线程尝试删除同一个表中的条目时,它们将进入死锁状态,其中sqlite3_step继续返回SQLITE_LOCKED。当我们调试代码时

10:00.234 Thread 1 BEGIN
10:00.235 Thread 1 select * from <table1>
10:00.234 Thread 1 select * from <table x>
10:00.456 Thread 1 delete from <table1>

10:00.456 Thread 2 BEGIN
10:00.456 Thread 2 select * from <table1>
10:00.906 Thread 2 select * from <table x>
10:01.156 Thread 2 delete from  <table1>

Thread 1 SQLITE_LOCKED(6) Error <Table1> is locked
Thread 2 SQLITE_LOCKED(6) Error database table is locked

线程1是第一个进入BEGIN并对表进行修改的线程,它应该已经获得了表上的WRITE锁定。即使我们认为线程2同时在同一个表上执行select,那么线程2应该在其delete调用中具有锁定表。在这种情况下,没有一个线程在表上锁定并且正在等待。在每个线程中,我们等待一段随机的时间重新执行(sqlite3_step)在准备好的语句上调用reset后的相同预处理语句。

在任何一个场景中,其中一个线程应该成为锁定此表的赢家。

我的问题是如何找到锁定桌子的人。有什么办法可以获得这些信息吗?当并发更新和插入正确发生时,为什么会发生删除?

0 个答案:

没有答案