Details
-
Bug
-
Status: Closed (View Workflow)
-
Minor
-
Resolution: Fixed
-
3.3.2, 3.3.3, 3.4.0
-
MariaDB J Connector
Description
XA_RBDEADLOCK causes a connection leak due to lack of rollback from narayana-jta
How to reproduce problem
1. if deadlock occurs on the database I get the following exception:
java.sql.SQLTransactionRollbackException: (conn=5107034) Deadlock found when trying to get lock; try restarting transaction
2. The transaction is marked as rollback only
3. Narayana-jta tries to end it by calling MariaDBXAResource.end
4. the database returns error code 1614, not handled in MariaDbXAResource.mapXaException, and xaErrorCode 0 is returned.
[jta ] ARJUNA016129: Could not end XA resource org.mariadb.jdbc.MariaXaResource@63140d36
java.sql.SQLException: XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected
[jta ] ARJUNA016045: attempted rollback of < formatId=131077, gtrid_length=29, bqual_length=36, tx_uid=0:ffff7f000101:a425:664dfd77:2bc441, node_name=1, branch_uid=0:ffff7f000101:a425:664dfd77:2bc442, subordinatenodename=null, eis_name=0 > (org.mariadb.jdbc.MariaXaResource@63140d36) failed with exception code ARJUNA016099: Unknown error code:0
5. therefore, the entire transaction ends with an error - and nothing more can be done with the connection because it is linked to the transaction on the database side
My solution to the problem is to add case to the 'mapXaException' function that handles error 1614 XA102, then narajana-jta rollback transaction correctly, and the connection can be used again.
private XAException mapXaException(SQLException sqle) {
int xaErrorCode;
switch (sqle.getErrorCode())
{ case 1397: xaErrorCode = XAException.XAER_NOTA; break; case 1398: xaErrorCode = XAException.XAER_INVAL; break; case 1399: xaErrorCode = XAException.XAER_RMFAIL; break; case 1400: xaErrorCode = XAException.XAER_OUTSIDE; break; case 1401: xaErrorCode = XAException.XAER_RMERR; break; case 1402: xaErrorCode = XAException.XA_RBROLLBACK; break; * case 1614: xaErrorCode = XAException.XA_RBDEADLOCK;* break; default: xaErrorCode = 0; break; } XAException xaException;
if (xaErrorCode != 0)
else
{ xaException = new XAException(sqle.getMessage()); } xaException.initCause(sqle);
return xaException;