我有一段使用myBatis,postgresql 9.3服务器和postgresql-9.3-1100-jdbc41 JDBC驱动程序的Java代码。 我们还使用mybatis-guice进行@Transactional支持。 到目前为止,我们一直只使用Serializable事务,现在我们希望将只从db中读取的查询放在一个不太严格的隔离级别,例如“read committed'”。因此,一些@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 LOG: execute : SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE 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 LOG: execute : BEGIN 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 LOG: execute : SELECT * FROM customer.accounts WHERE -- 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 LOG: execute : UPDATE customer.cities SET name = $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 DETAIL: parameters: ...... 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: execute : SELECT l.* , cc.id as cost_center_id, cc.description as 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 DETAIL: parameters: $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: execute : UPDATE customer.ledgers SET 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 DETAIL: parameters: $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: execute : SELECT DISTINCT role FROM customer.user_roles ur INNER JOIN customer.user_to_accounts_to_user_roles uur ON (ur.id=uur.role_id) WHERE 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 DETAIL: parameters: $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: execute 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 LOG: execute : BEGIN 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 LOG: execute : SELECT id FROM customer.user_roles WHERE role=$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 DETAIL: parameters: $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 LOG: execute : INSERT INTO customer.user_to_accounts_to_user_roles (user_id, account_id, role_id) values ($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 DETAIL: parameters: $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 LOG: execute S_1: COMMIT 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 LOG: execute : SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ COMMITTED 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 LOG: execute : BEGIN 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 LOG: execute : SELECT * FROM customer.cities WHERE -- 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 DETAIL: parameters: $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 LOG: execute S_1: COMMIT
(这是一个片段,通过grepping sessionId和使用--after-context进行过滤 - 这就是为什么有些查询似乎没有终结,但相信我,他们是有效的查询)。 所以我有一个成功查询的列表,并且在某些时候发布了ROLLBACK。然后代码继续其余的查询。所以我似乎没有在代码中有任何例外。似乎ROLLBACK是出乎意料地发布的。
怎么会发生这种情况?
这种情况就像10次中的10次一样,10次中有9次一切正常(使用相同的数据)。代码是多线程的。
我可以提供其他细节,没问题。
答案 0 :(得分:0)
我在此期间找到了原因。
在一个用@Transactional注释的方法里面(让我们调用这个方法A),还有另一个用@Transactional注释的方法(让我们调用这个方法B)。这个内部方法(methodB)引发了一个异常,例外是方法A中的例外,代码很快就开始了。但是,只要myBatis看到异常,它就会回滚整个事务。
这样的事情:
class Point { double X, Y; }