【问题标题】:Why does myBatis+postgresql 9.3 issue a ROLLBACK even if the query succeeds?为什么myBatis+postgresql 9.3即使查询成功也会发出ROLLBACK?
【发布时间】:2016-02-09 16:22:23
【问题描述】:

我有一段使用 myBatis、postgresql 9.3 服务器和 postgresql-9.3-1100-jdbc41 JDBC 驱动程序的 Java 代码。 我们还使用 mybatis-guice 来支持 @Transactional。 到目前为止,我们一直只使用可序列化事务,现在我们希望将只从数据库读取的查询置于不太严格的隔离级别,例如“已提交读”。因此,一些@Transactional 注释使用SERIALIZABLE,其中一些使用READ_COMMITTED。还有嵌套调用。

所以,我在 postgresql 服务器日志中有这个:

2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1268 txnId=0 pid=1949 appName=entity_manager 日志:执行:设置会话特征作为事务隔离级别可序列化 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=0 pid=1949 appName=entity_manager 日志:执行:开始 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=0 pid=1949 appName=entity_manager 日志:执行:选择 * 从 客户.accounts 在哪里 -- 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=0 pid=1949 appName=entity_manager 日志:执行:更新 客户.城市 放 名称 = 1 美元, ledger_id = $2, -- 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=0 pid=1949 appName=entity_manager 详细信息:参数:... ... 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=1726978 pid=1949 appName=entity_manager 日志:执行:选择 l.* , cc.id 作为 cost_center_id, cc.description 作为 cost_center_description, -- 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=1726978 pid=1949 appName=entity_manager 详细信息:参数:$1 = 。 …… 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=1726978 pid=1949 appName=entity_manager 日志:执行:更新 客户账本 放 internal_ledger_number = $1 , -- 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=1726978 pid=1949 appName=entity_manager 详细信息:参数:$1 = 。 ………… 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=1726978 pid=1949 appName=entity_manager 日志:执行:选择 DISTINCT 角色 FROM customer.user_roles ur INNER JOIN customer.user_to_accounts_to_user_roles uur ON (ur.id=uur.role_id) 在哪里 user_id=$1 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=1726978 pid=1949 appName=entity_manager 详细信息:参数:$1 = 。 …… 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1269 txnId=1726978 pid=1949 appName=entity_manager LOG:执行 S_2:ROLLBACK 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1270 txnId=0 pid=1949 appName=entity_manager 日志:执行:开始 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1270 txnId=0 pid=1949 appName=entity_manager 日志:执行:选择 ID 从 customer.user_roles WHERE 角色=$1 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1270 txnId=0 pid=1949 appName=entity_manager 详细信息:参数:$1 = 。 ...... 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1270 txnId=0 pid=1949 appName=entity_manager 日志:执行:插入客户.user_to_accounts_to_user_roles (user_id, account_id, role_id) 价值观 (1 美元、2 美元、3 美元) 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1270 txnId=0 pid=1949 appName=entity_manager 详细信息:参数:$1 = 。 ………… 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1270 txnId=1726979 pid=1949 appName=entity_manager 日志:执行 S_1:提交 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1271 txnId=0 pid=1949 appName=entity_manager 日志:执行:设置会话特征事务隔离级别已提交 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1272 txnId=0 pid=1949 appName=entity_manager 日志:执行:开始 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1272 txnId=0 pid=1949 appName=entity_manager 日志:执行:选择 * 从 客户.城市 在哪里 -- 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1272 txnId=0 pid=1949 appName=entity_manager 详细信息:参数:$1 = 。 ...... 2016-02-09 15:27:47 CET sessionId=56b9f455.79d sessionStart=2016-02-09 15:14:45 CET vTxnId=12/1272 txnId=0 pid=1949 appName=entity_manager 日志:执行 S_1:提交

(这是一个 sn-p,通过对 sessionId 进行 grepping 并使用 --after-context 进行过滤 - 这就是为什么某些查询似乎未终止的原因,但相信我,它们是有效的查询)。 因此,我有一个成功查询的列表,并且在某些时候发出了 ROLLBACK。然后代码继续其余的查询。所以我在代码中似乎没有任何异常。而且似乎 ROLLBACK 是突然发出的。

怎么会这样?
这种情况就像 10 次中的 1 次,10 次中的 9 次一切正常(使用相同的数据)。代码是多线程的。

我可以提供其他细节,没问题。

【问题讨论】:

    标签: java postgresql mybatis transactional


    【解决方案1】:

    我已经找到了原因。

    原来在一个用@Transactional 注解的方法(我们称之为methodA)内部还有另一个用@Transactional 注解的方法(我们称之为methodB)。这个内部方法(methodB)抛出了异常,异常在methodA中被咳出,代码愉快地继续。然而,一旦 myBatis 发现异常,它就会回滚整个事务。

    类似这样的:

    methodA (@Transactional)
    begin
    select * ....
    update .....
    methodB: select .... 
    methodB: throw exception -> myBatis calls rollback
    methodA: catch exception, go on
    methodA: other code
    

    【讨论】:

      猜你喜欢
      • 2017-09-29
      • 2012-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-28
      • 2018-05-24
      相关资源
      最近更新 更多