У меня есть приложение Java / WebSphere, которое выполняет транзакции XA с экземпляром SQL Server 2008. В некоторых средах все работает должным образом. В двух наших средах транзакции периодически завершаются ошибкой.
Немного информации об окружающей среде:
На сервере приложений я вижу такие трассировки стека, когда транзакция не выполняется:
com.microsoft.sqlserver.jdbc.SQLServerException: Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1515)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:404)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:314)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.pmiExecuteUpdate(WSJdbcPreparedStatement.java:1187)
at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeUpdate(WSJdbcPreparedStatement.java:804)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:186)
Когда я смотрю журналы MSDTC на сервере базы данных, я вижу следующее:
time=12/22/2015-10:47:48.611 eventid=RM_ENLISTED_IN_TRANSACTION tx_guid=690a94a2-a060-4eb9-8966-ef25b0fa001b resource manager #1001 enlisted as transaction enlistment #1. RM guid = '280f3497-9cc1-4689-b612-7a08cce82e2b'
time=12/22/2015-10:47:57.612 eventid=ABORT_DUE_TO_TRANSACTION_TIMER_EXPIRED tx_guid=690a94a2-a060-4eb9-8966-ef25b0fa001b transaction timeout expired
time=12/22/2015-10:47:57.612 eventid=TRANSACTION_ABORTING tx_guid=690a94a2-a060-4eb9-8966-ef25b0fa001b transaction is aborting
time=12/22/2015-10:47:57.612 eventid=RM_ISSUED_ABORT tx_guid=690a94a2-a060-4eb9-8966-ef25b0fa001b abort request issued to resource manager #1001 for transaction enlistment #1
time=12/22/2015-10:47:57.612 eventid=RM_ACKNOWLEDGED_ABORT tx_guid=690a94a2-a060-4eb9-8966-ef25b0fa001b received acknowledgement of abort request from the resource manager #1001 for transaction enlistment #1
time=12/22/2015-10:47:57.612 eventid=TRANSACTION_ABORTED tx_guid=690a94a2-a060-4eb9-8966-ef25b0fa001b transaction has been aborted
Я постоянно вижу, как событие ABORT_DUE_TO_TRANSACTION_TIMER_EXPIRED происходит через 9 секунд после события RM_ENLISTED_IN_TRANSACTION. Проблема в том, что тайм-аут транзакции MSDTC на сервере базы данных настроен на 60 секунд. Я попытался изменить этот тайм-аут, и это никак не повлияло на поведение. Я не вижу никаких настроек тайм-аута транзакции в WebSphere, которые соответствовали бы 9-секундному интервалу. Откуда этот таймаут и как его изменить?
Мы разобрались с нашей проблемой. У нас было другое приложение, не относящееся к WebSphere, которое использовало Atomikos для транзакций JTA. Atomikos по умолчанию устанавливает 10-секундный тайм-аут для своей транзакции по умолчанию, если вы не установите свойство com.atomikos.icatch.default_jta_timeout. Atomikos устанавливает этот тайм-аут для всех экземпляров XAResource, участвующих в транзакции. По какой-то причине это привело к глобальному применению 10-секундного тайм-аута ко всем транзакциям, использующим этот экземпляр MSDTC. Также стоит отметить, что диспетчер транзакций WebSphere НЕ вызывает setTimeout для участвующих экземпляров XAResource, что может быть одной из причин, по которой другое приложение влияло на эти транзакции. Перезапуск MSDTC, кажется, очищает этот глобальный тайм-аут до повторного запуска транзакции Atomikos.
Вероятно, стоит отметить, что другие менеджеры транзакций JTA, такие как Bitronix, могут иметь те же проблемы при доступе к SQL Server с помощью XA. Эта проблема также может быть специфичной для драйвера JDBC SQL Server версии 4.0 и может быть исправлена в более поздних версиях. Однако я не могу проверить эти утверждения.
Если у вас возникнет такая же проблема, вы сможете проверить ее, выполнив следующие действия: