2016-08-19 22 views
0

SQLサーバーで動作するJavaベースのWebアプリケーションを構築しています。WebアプリケーションのSQLサーバーデータベース分離レベル

SQLサーバーのデフォルトのデータベース分離レベルはREAD_COMMITTEDです。

私は、次の例外を取得:

Cause: org.hibernate.exception.LockAcquisitionException: Transaction (Process ID 124) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 

    2016-08-18 07:23:36.064 ERROR application 

    Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Transaction (Process ID 124) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 
     at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) ~[com.microsoft.sqlserver.sqljdbc4-4.0.jar:na] 
     at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:4853) ~[com.microsoft.sqlserver.sqljdbc4-4.0.jar:na] 
     at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1781) ~[com.microsoft.sqlserver.sqljdbc4-4.0.jar:na] 
     at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:1034) ~[com.microsoft.sqlserver.sqljdbc4-4.0.jar:na] 
     at sun.reflect.GeneratedMethodAccessor25.invoke(Unknown Source) ~[na:na] 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_74] 
     at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_74] 
     at org.hibernate.engine.jdbc.internal.proxy.AbstractResultSetProxyHandler.continueInvocation(AbstractResultSetProxyHandler.java:104) ~[org.hibernate.hibernate-core-4.1.9.Final.jar:4.1.9.Final] 
     ... 82 common frames omitted 

誰かがそれについての詳細な情報を与えることができますか?

+0

https://technet.microsoft.com/en-us/library/ms178104 %28v = sql.105%29.aspx –

+0

同じアプリケーションはMariadbでデッドロックなしでかなりうまく動作しますが、私はちょっと混乱しています。 –

答えて

0

デフォルトでは、SQL Serverは悲観的なロックを使用します。これは、トランザクション内で行が読み取られたり更新されたりすると、そのトランザクションによってロックされて他のトランザクションが読み書きできなくなる(最初のトランザクションがコミットされるまで他のトランザクションはブロックされます)。

デッドロックは、 2つのトランザクションが同じデータを読み取っており、両方とも他のトランザクションが読み取っていた行をロックしています。 あなたが名前と2行というカラムに持つテーブルがあります:簡単な例を取ると

名:
フー
バー

トランザクション1は、fooは(それがロックさせる)を読み込みます
トランザクション2がバーを読み取ってロックします
トランザクション1はバーを読み取ろうとしますが、トランザクション2がコミットするまでブロックします
トランザクション2はFooを読み取ろうとしますが、トランザクション1によってブロックされました。

これでデッドロックが発生しました。両方のトランザクションがもう一方のリソースを解放するのを待っています。 SQLサーバーにはデッドロックを検出するための内部メカニズムがあり、デッドロックを検出してロールバックする1つのトランザクションを選択します。デッドロックの犠牲者として選択されたトランザクションを持つjavaスレッドは、あなたの例のようなエラーを返します。

ソリューション: ここでは、いくつかのオプション

  1. 可能な場合があり、読み込まれた行が常に同じ順序で読み込まれるように、両方のトランザクションが読めば、上記の例では(自分のコードを変更foo最初のトランザクション2は、トランザクション1が完了するのを単に待つ)

  2. デッドロックは、同時アプリケーションの一部である可能性があり、このエラーが発生した場合にリクエストを再送信するか、スローされます。 (理想的ではありませんが、問題の頻度によっては時々これらのエラーが発生することを実用的にしています)

  3. 代替のロック方法を見てください。 SQL Serverはいくつかの機能をサポートしていますが、悲観的なロック(あなたの例ではデフォルトと同じ)とオプティミスティック・ロック(スナップショット・アイソレーションと呼ばれることもあります)の2つのカテゴリに大まかに分類できます。
    オプティミスティック・ロックでは、複数のトランザクションでロックなしで同じ行を読み取ることができます。ロックは書き込み専用です。両方の方法に長所と短所があり、これを変えると問題が変わる可能性があります。
    上記の例では、楽観的ロックは、2つのトランザクションが読んでいるだけなので、これを解決します。しかし、2つのトランザクションがレコードを挿入または更新していた場合、2つのトランザクションが同じレコードを更新しようとすると(どちらのトランザクションも読み取ったがコミットしていない)、最後にコミットするトランザクションが楽観的になるロックエラー。
    他にも多くの分野があり、より詳細な記事があります。

    https://technet.microsoft.com/en-us/library/jj856598(v=sql.110).aspx

https://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx

関連する問題