トランザクションの連続番号を生成する必要があります。同時ユーザーが同時にトランザクションを予約しようとすると、sqlcode = -911、sqlstate = 40001、sqlerrmc = 2(デッドロック)が発生しました。現在、デッドロックは、同じレコードを読み込んで更新しているために発生します。どのようにデッドロックを防ぐことができるようにこれを設計できますか?デッドロックが発生したシーケンシャル番号の生成
答えて
この問題にはいくつかの方法があり、他の方法よりもパフォーマンスが低いものがあります。
すべてのオブジェクトが同じ階層的な順序でロックされていると、デッドロックを防ぐことができます。しかし、デッドロックを完全に防止するダイエット哲学者の問題に対する解決策は、単にトランザクションをロールバックして再試行するよりもパフォーマンスが低いことが多い。ソリューションをテストする必要があります。
データ側のソリューションを探している場合、厳密なロックシーケンスを確立することによって、新しいトランザクション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)。 「シード」テーブルでUPDATEのカーソルを開き、現在の行をフェッチします。これにより、シード値を排他的に制御できます。 2)。このフェッチされた行を「次の値」として使用します。ただし、これを行う前に 3)。取得した「次の値」をインクリメントして更新をコミットします。このコミットはカーソルを閉じ、シード行を新しい「次の値」で解放します。
"次の値"を自由に使用できます。
このアプローチについて説明している可能性のある他の名前:High-Water Mark、Sequence-ID Table、およびMaster Transaction Table。 ++ Hectorは、専用テーブルをプロセスに効率的に使用するためのものです。 CURSORが単純なTRANSACTION境界よりも効率的であるかどうかはわかりませんが、両方で再生して自分の環境で動作するものを確認できます。 –
Iveは多くのエンタープライズ運用システムでCursor for updateアプローチを使用していました。このアプローチでは、「次の値」のリクエストを整然とした方法でキューに入れています。メインフレームのz/OS DB2上でTPS 100 - > 1000をサポートしています。 – Hector
非常に良い。私は、私の個人的な「余分な時間」を追加して、2つの手法のパフォーマンス比較を実行しようとするリストを作成すると思います。なぜなら、知っていることは素晴らしく、遊びは楽しいからです。 :-) –
- 1. C#エンティティを生成するシーケンシャル番号
- 2. SQL Azureフェデレーションでシーケンシャル番号を効率的に生成する
- 3. シーケンシャルURLの番号
- 4. mapreduceのシーケンシャル番号
- 5. ランダム番号生成
- 6. SQL Server - 更新時に一意のシーケンシャル番号を生成する方法
- 7. データベースエラーがCodeIgniterのエラー番号で発生しました:1048
- 8. シリアル番号の生成
- 9. シーケンス番号の生成は
- 10. ID番号の生成
- 11. 例外が発生した場合のファイル名と行番号
- 12. PHPエラーが発生しました - コード番号
- 13. データベースエラーが発生しましたエラー番号:1064
- 14. C++ランダム生成番号
- 15. 抽選番号生成プログラム
- 16. アイテム番号生成テーブル - Excel
- 17. SQL生成グループ番号
- 18. プログラムのデッドロックが発生する
- 19. C乱数発生器で時々同じ番号が生成される
- 20. オペレーティングシステムでデッドロックが発生する頻度(発生する頻度)
- 21. Go:go channelでデッドロックの問題が発生しました
- 22. Googleトークン確認のコールにデッドロックが発生しましたか?
- 23. Ruby:オープンでデッドロックが発生する
- 24. エラーが発生した場所から行番号の代わりにエラーが発生した行番号を取得する方法Django
- 25. 最新のオペレーティングシステムでデッドロックが発生した場合は、
- 26. AFHTTPSessionManagerフリーズ/デッドロックが発生しましたか?
- 27. Sybase ASE:「サーバーコマンドでデッドロックが発生しました」
- 28. Task.Runとデッドロックが発生しましたか?
- 29. PHPでシーケンシャルIDを生成したいが、ランダムではない。
- 30. は、エラー番号を発生しました:1054
デッドロックの原因を正確に特定するための情報、呼び出しコードとは何か、dbデザインは何ですか?現在は何も進んでいません。 – GurV
そのような状況で通常行うことは、例外をキャッチしてもう一度やり直すことです。別の方法として、データベーステーブルにトランザクションを作成し、データベース自体がデータベースのプライマリキーを生成できるようにする方法があります。 –
同期キーワードを使用すると、デッドロックを防ぐことができます。 synchronizedブロックは、現在のスレッドがオブジェクトのモニタに正常に入力した後にのみ、オブジェクトのメンバであるメソッドへの呼び出しが確実に行われるようにします。スレッドがインスタンス上の同期メソッドに入ると、他のスレッドは他のスレッドに同期することができません。 – Tehmina