我们在OSX(10.10.4)上有一个C ++应用程序,在MacBook Pro(无VM)上本地运行,使用SQLite 3.7.7.1(旧的,我意识到),并且我看到以下行为:< / p>
app的线程1连接到file1.db(在Journaled HFS +分区上),创建一个保存点,将行插入table1,然后释放保存点。
同一应用程序的线程2与file2.db有连接,并且先前已在同一连接中附加了file1.db。它现在尝试通过从file1.table1中选择插入到file2.table2中。
如果1&amp; 2发生在一起(在1秒内),我们看到在步骤1中插入的行没有插入到table2中。但如果我们在第1步和第1步之间等待1秒2,我们总是看到插入的行。在步骤1提交之后肯定会发生第2步,因为我们正在记录语句并且可以观察它。
我们正在默认的journal_mode(删除)中运行。
在journal_mode = delete时,同一应用程序共享的连接之间是否存在某种传播延迟?隔离级别(https://www.sqlite.org/isolation.html)的规则并不明确禁止它。
答案 0 :(得分:0)
解决问题:
这种行为的根源是由于我们对保存点的工作方式存在误解。具体来说,回滚保存点不会删除保存点,因此在&#34; ROLLBACK TO&#34;之后对连接进行后续操作。命令仍在原始保存点的事务中。
在我们的例子中,在步骤1中描述的保存点之前有一个保存点已经回滚,这样线程1在其释放的保存点内工作仍然对其他连接不可见。使用与先前回滚的保存点同名的保存点在线程1中的后续操作是RELEASED,它最终从线程1提交数据,这就是为什么我们看到数据稍后出现在线程2的连接中。
由于我们使用简单的Savepoint类作为堆栈创建的保护对象,它跟踪我们在创建保存点时嵌套的级别(这是保存点名称被重用的方式),解决方案只是为了确保创建的最外面的保存点(即,当该连接上当前没有其他保存点时创建的保存点)使用&#34; BEGIN TRANSACTION&#34; /&#34; COMMIT&#34; /& #34; ROLLBACK&#34;并且在那个中创建的所有保存点都使用&#34; SAVEPOINT SP_1&#34;,&#34; SAVEPOINT_SP2&#34;等