Seam&Hibernate(JDBCからSQLServer)で動作するSeamWebアプリケーションがあります。
正常に動作していますが、高負荷(JMeterによるストレステスト)では、いくつかLockAcquisitionException
またはがありOptimisticLockException
ます。
これLockAquisitionException
は、SQLServerException
「トランザクション(プロセスID 64)が別のプロセスとのロックリソースでデッドロックし、デッドロックの犠牲者として選択されました。トランザクションを再実行してください」が原因です。
次に、そのようなトランザクションを再実行するためのSeamInterceptorを作成しましたLockAquisitionException
。
@AroundInvoke
public Object aroundInvoke(final InvocationContext invocationContext) throws Exception {
if (instanceThreadLocal.get() == null && isMethodInterceptable(invocationContext)) {
try {
instanceThreadLocal.set(this);
int i = 0;
PersistenceException exception = null;
do {
try {
return invocationContext.proceed();
} catch (final PersistenceException e) {
final Throwable cause = e.getCause();
if (!(cause instanceof LockAcquisitionException)) {
throw e;
}
exception = e;
i++;
if (i < MAX_RETRIES_LOCK_ACQUISITION) {
log.info("Swallowing a LockAcquisitionException - #0/#1", i, MAX_RETRIES_LOCK_ACQUISITION);
try {
if (Transaction.instance().isRolledBackOrMarkedRollback()) {
Transaction.instance().rollback();
}
Transaction.instance().begin();
} catch (final Exception e2) {
throw new IllegalStateException("Exception while rollback the current transaction, and begining a new one.", e2);
}
Thread.sleep(1000);
} else {
log.info("Can't swallow any more LockAcquisitionException (#0/#1), will throw it.", i, MAX_RETRIES_LOCK_ACQUISITION);
throw e;
}
}
} while (i < MAX_RETRIES_LOCK_ACQUISITION);
throw exception;
} finally {
instanceThreadLocal.remove();
}
}
return invocationContext.proceed();
}
最初の質問:このインターセプターは正しく機能すると思いますか?
グーグルで調べて、Alfresco(ここでフォーラムトークを使用)を見ると、BonitaとOrchestraStaleObjectStateException
にはそのようなトランザクションを再実行する方法がいくつかあり、たとえば(私の原因)のように、はるかに多くの例外をキャッチしていますOptimisticLockException
。
私の2番目の質問は次のとおりです:(StaleObjectStateException
「行が別のトランザクションによって更新または削除された(または保存されていない値のマッピングが正しくなかった)」)の場合、データベースと@Version
フィールドとの同期の問題であるため、通常はトランザクションを再実行することはできませんではない ?たとえば、Alfrescoがそのような例外によって引き起こされたそのようなトランザクションを再実行しようとするのはなぜですか?
編集:LockAcquisitionException
によって引き起こされたためSQLServerException
、私はウェブ上のいくつかのリソースを見てきました、そして私が私のコードを再確認する必要があるとしても、それはとにかく起こる可能性があるようです...ここにリンクがあります:
- このテーマに関する記事(リソースが不足することによっても発生する可能性があるというコメント付き)
- サブリンクのある別の記事:
Microsoftでさえ、「デッドロックを最小限に抑えることはできますが、完全に回避することはできません。そのため、フロントエンドアプリケーションはデッドロックを処理するように設計する必要があります。」