【问题标题】:SQLite in-memory database encounters SQLITE_LOCKED_SHAREDCACHE intermittentlySQLite 内存数据库间歇性地遇到 SQLITE_LOCKED_SHAREDCACHE
【发布时间】:2020-12-01 07:58:42
【问题描述】:

我正在使用 mybatis 3.4.6 和 org.xerial:sqlite-jdbc 3.28.0。下面是我使用启用共享模式的内存数据库

的配置
db.driver=org.sqlite.JDBC
db.url=jdbc:sqlite:file::memory:?cache=shared

根据这个test classdb.url是正确的

虽然我也报告了这个issue,但属性 read_uncommitted 存在拼写错误,但我设法使用以下 mybatis 配置设置了正确的事务隔离级别

<environment id="${db.env}">
    <transactionManager type="jdbc"/>
    <dataSource type="POOLED">
        <property name="driver" value="${db.driver}" />
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />
        <property name="defaultTransactionIsolationLevel" value="1" />
        <property name="driver.synchronous" value="OFF" />
        <property name="driver.transaction_mode" value="IMMEDIATE"/>
        <property name="driver.foreign_keys" value="ON"/>
    </dataSource>
</environment>

这一行配置

  <property name="defaultTransactionIsolationLevel" value="1" />

设置正确的 PRAGMA read_uncommitted

值的技巧

我很确定,因为我调试了初始化连接的底层代码并检查了值是否设置正确

但是通过上述设置,我的程序在读取时仍然间歇性地遇到 SQLITE_LOCKED_SHAREDCACHE,根据下面屏幕截图红色矩形突出显示的描述,我认为它不应该发生。我想知道原因和解决方法,虽然这个错误发生的概率很低。

任何想法将不胜感激!

调试配置如下


===CONFINGURATION==============================================
 jdbcDriver                     org.sqlite.JDBC
 jdbcUrl                        jdbc:sqlite:file::memory:?cache=shared
 jdbcUsername                   
 jdbcPassword                   ************
 poolMaxActiveConnections       10
 poolMaxIdleConnections         5
 poolMaxCheckoutTime            20000
 poolTimeToWait                 20000
 poolPingEnabled                false
 poolPingQuery                  NO PING QUERY SET
 poolPingConnectionsNotUsedFor  0
 ---STATUS-----------------------------------------------------
 activeConnections              5
 idleConnections                5
 requestCount                   27
 averageRequestTime             7941
 averageCheckoutTime            4437
 claimedOverdue                 0
 averageOverdueCheckoutTime     0
 hadToWait                      0
 averageWaitTime                0
 badConnectionCount             0
===============================================================

附件:

异常如下

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: org.apache.ibatis.transaction.TransactionException: Error configuring AutoCommit.  Your driver may not support getAutoCommit() or setAutoCommit(). Requested setting: false.  Cause: org.sqlite.SQLiteException: [SQLITE_LOCKED_SHAREDCACHE]  Contention with a different database connection that shares the cache (database table is locked)
### The error may exist in mapper/MsgRecordDO-sqlmap-mappering.xml
### The error may involve com.super.mock.platform.agent.dal.daointerface.MsgRecordDAO.getRecord
### The error occurred while executing a query
### Cause: org.apache.ibatis.transaction.TransactionException: Error configuring AutoCommit.  Your driver may not support getAutoCommit() or setAutoCommit(). Requested setting: false.  Cause: org.sqlite.SQLiteException: [SQLITE_LOCKED_SHAREDCACHE]  Contention with a different database connection that shares the cache (database table is locked)

【问题讨论】:

  • 这可能是因为我在那张桌子上使用了trigger 吗? trigger 会持有该表的排他锁吗?

标签: java sqlite mybatis sqlitejdbc


【解决方案1】:

我终于自己解决了这个问题,并在下面分享了解决方法,以防其他人将来遇到类似问题。

首先,我们可以得到如下所示异常的完整调用栈

通过回调指示的源代码,我们有以下发现。

  1. SQLite 是内置的,默认启用 auto commit,这与 MyBatis 相矛盾,MyBatis 默认禁用 auto commit,因为我们使用的是 SqlSessionManager
  2. MyBatis 将在连接初始化期间使用方法setDesiredAutoCommit 覆盖自动提交属性,该方法最终调用SQLiteConnection#setAutoCommit
  3. SQLiteConnection#setAutoCommit 将导致对数据库执行 begin immediate 操作,这实际上是独占的,请查看下面的源代码屏幕截图以获取详细说明,因为我们将事务模式配置为 IMMEDIATE

&lt;property name="driver.transaction_mode" value="IMMEDIATE"/&gt;

所以到目前为止,一个明显的解决方案是将事务模式更改为DEFERRED。另外,也考虑过让MyBatis和SQLite的auto commit设置相同的方案,但是由于在初始化阶段无法设置SQLiteConnection的自动提交,所以没有采用,总会有切换(从真到假,反之亦然),如果交易模式设置不正确,切换可能会导致上述错误

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 2016-07-28
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 2020-10-20
    相关资源
    最近更新 更多