Назад | Перейти на главную страницу

Таймауты транзакций XA с SQL Server, MSDTC и WebSphere

У меня есть приложение 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 и может быть исправлена ​​в более поздних версиях. Однако я не могу проверить эти утверждения.

Если у вас возникнет такая же проблема, вы сможете проверить ее, выполнив следующие действия:

  1. Перезапустить MSDTC
  2. Выполняйте транзакции в своем приложении WebSphere. Они никогда не должны выходить из строя из-за тайм-аутов. Попробуйте несколько транзакций - достаточно, чтобы чувствовать себя комфортно.
  3. Запустите транзакцию с вашим приложением Atomikos.
  4. Снова запустите транзакцию с WebSphere. Если транзакция превышает 10 секунд, она должна завершиться ошибкой и быть прервана MSDTC.
  5. Перезапустить MSDTC
  6. Снова запустите транзакцию с WebSphere. Ошибки тайм-аута больше не должны возникать, даже если они превышают 10 секунд.