2017-08-03 7 views
0

トランザクションの連続番号を生成する必要があります。同時ユーザーが同時にトランザクションを予約しようとすると、sqlcode = -911、sqlstate = 40001、sqlerrmc = 2(デッドロック)が発生しました。現在、デッドロックは、同じレコードを読み込んで更新しているために発生します。どのようにデッドロックを防ぐことができるようにこれを設計できますか?デッドロックが発生したシーケンシャル番号の生成

+2

デッドロックの原因を正確に特定するための情報、呼び出しコードとは何か、dbデザインは何ですか?現在は何も進んでいません。 – GurV

+1

そのような状況で通常行うことは、例外をキャッチしてもう一度やり直すことです。別の方法として、データベーステーブルにトランザクションを作成し、データベース自体がデータベースのプライマリキーを生成できるようにする方法があります。 –

+0

同期キーワードを使用すると、デッドロックを防ぐことができます。 synchronizedブロックは、現在のスレッドがオブジェクトのモニタに正常に入力した後にのみ、オブジェクトのメンバであるメソッドへの呼び出しが確実に行われるようにします。スレッドがインスタンス上の同期メソッドに入ると、他のスレッドは他のスレッドに同期することができません。 – Tehmina

答えて

0

この問題にはいくつかの方法があり、他の方法よりもパフォーマンスが低いものがあります。

すべてのオブジェクトが同じ階層的な順序でロックされていると、デッドロックを防ぐことができます。しかし、デッドロックを完全に防止するダイエッ​​ト哲学者の問題に対する解決策は、単にトランザクションをロールバックして再試行するよりもパフォーマンスが低いことが多い。ソリューションをテストする必要があります。

データ側のソリューションを探している場合、厳密なロックシーケンスを確立することによって、新しいトランザクションIDの取得をアトミックにすることが昔ながらの(そして潜在的にパフォーマンスの低い)アプローチです。

Quick-ishソリューション(製品にリリースする前に負荷をテストしてください)はTRANSACTION境界を使用し、制御行をゲートキーパーとして使用できます。ここでは、基本的なテクニックを示す愚かな例があります。 これはエラーチェックがなく、ゴーストIDを再利用するためのコードは、この例の範囲外である:

DECLARE @NewID INTEGER; 
BEGIN TRANSACTION; 
UPDATE [TABLE] SET [LOCKFLAG] = CURRENT_TIMESTAMP WHERE [ROW_ID] = 0; 
SELECT @NewID = MAX([ROW_ID])+1 FROM [TABLE]; 
INSERT INTO [TABLE] ([ROW_ID]) VALUES (@NewID); 
UPDATE [TABLE] SET [LOCKFLAG] = NULL WHERE [ROW_ID] = 0; 
COMMIT TRANSACTION; 

アイデアは、持続時間が非常に、非常に短いこの原子、シングルスレッド、シリアル化された操作を行うことです - - do IDを安全に予約して退出するために必要なこと。

すべてのID要求がこの規格に準拠すれば、行0を更新するための最初の手順を実行することで、競合するユーザーはその最初の手順の後ろに単純にキューイングされます。

あなたのIDが予約されたら、あなたの好きなことをしてください。新しい取引を使って、作成した行を更新することができます。

テーブルにゴースト列があるため、後の手順でROLLBACKとするケースをカバーする必要があります。あなたはそれらを取り戻す方法を望むでしょう。様々な単純な解決策を使用することができる。

1

単一のデータ行を含む「シード」テーブルを作成します。 この「シード」テーブル行には、「次の順次」値が保持されます。

「次の順次」値を使用して新しいビジネスデータ行を挿入する場合。次の手順を実行します。

1)。 「シード」テーブルでUPDATEのカーソルを開き、現在の行をフェッチします。これにより、シード値を排他的に制御できます。 2)。このフェッチされた行を「次の値」として使用します。ただし、これを行う前に 3)。取得した「次の値」をインクリメントして更新をコミットします。このコミットはカーソルを閉じ、シード行を新しい「次の値」で解放します。

"次の値"を自由に使用できます。

+1

このアプローチについて説明している可能性のある他の名前:High-Water Mark、Sequence-ID Table、およびMaster Transaction Table。 ++ Hectorは、専用テーブルをプロセスに効率的に使用するためのものです。 CURSORが単純なTRANSACTION境界よりも効率的であるかどうかはわかりませんが、両方で再生して自分の環境で動作するものを確認できます。 –

+0

Iveは多くのエンタープライズ運用システムでCursor for updateアプローチを使用していました。このアプローチでは、「次の値」のリクエストを整然とした方法でキューに入れています。メインフレームのz/OS DB2上でTPS 100 - > 1000をサポートしています。 – Hector

+0

非常に良い。私は、私の個人的な「余分な時間」を追加して、2つの手法のパフォーマンス比較を実行しようとするリストを作成すると思います。なぜなら、知っていることは素晴らしく、遊びは楽しいからです。 :-) –

関連する問題