18

データベースのデッドロックが発生する従来の理由の 1 つは、2 つのトランザクションが異なる順序でテーブルを挿入および更新している場合です。

たとえば、トランザクション A はテーブル A に挿入し、次にテーブル B に挿入します。

そして、トランザクション B がテーブル B に挿入され、その後に A が続きます。

このようなシナリオでは、常にデータベース デッドロックのリスクがあります (シリアライズ可能な分離レベルを使用していないと仮定します)。

私の質問は次のとおりです。

  1. すべてのトランザクションが同じ順序で挿入および更新されるようにするために、設計でどのようなパターンに従いますか。私が読んでいた本には、テーブルの名前でステートメントを並べ替えることができるという提案がありました。このようなことや別のことをしたことがありますか - すべての挿入と更新が同じ順序になることを強制しますか?

  2. レコードの削除についてはどうですか?削除は子テーブルから開始する必要があり、更新と挿入は親テーブルから開始する必要があります。これがデッドロックに陥らないようにするにはどうすればよいでしょうか?

4

6 に答える 6

7

デッドロックは大したことではありません。失敗した場合にトランザクションを再試行する準備をしてください。

そして、それらを短くしてください。(インデックス作成の魔法を使用して) ごく少数のレコードに触れるクエリで構成される短いトランザクションは、デッドロックを最小限に抑えるのに理想的です。

最新のデータベース エンジンはテーブルをロックしないことを知っておく必要があります。行をロックします。そのため、デッドロックの可能性は少し低くなります。

MVCC と CONSISTENT READ トランザクション分離レベルを使用してロックを回避することもできます。ロックする代わりに、一部のスレッドは古いデータを参照するだけです。

于 2009-04-10T16:28:50.567 に答える
2

デッドロックを回避するためにこれまでに行った最善の投資の 1 つは、データベースの更新を注文できるオブジェクト リレーショナル マッパーを使用することであることがわかりました。すべてのトランザクションが同じ順序で書き込みを行う (そしてまったく逆の順序で削除する) 限り、正確な順序は重要ではありません。

これによりすぐに使用できるほとんどのデッドロックが回避される理由は、操作が常に最初にテーブル A、次にテーブル B、次にテーブル C (おそらくテーブル B に依存する) であるためです。

ストアド プロシージャまたはデータ層のアクセス コードに注意を払う限り、同様の結果を得ることができます。唯一の問題は、手作業で行うには細心の注意が必要ことですが、Unit of Work の概念を持つ ORM はほとんどのケースを自動化できます。

更新: 削除は順方向に実行して、すべてが期待どおりのバージョンであることを確認し (レコードのバージョン番号またはタイムスタンプが必要です)、すべてが確認されたら逆方向に削除する必要があります。これはすべて 1 つのトランザクションで発生する必要があるため、あなたの下から何かが変わる可能性はありません。ORM が逆方向に実行する唯一の理由は、重要な要件に従うことですが、チェックを順方向に実行すると、必要なすべてのロックが既に手元にあることになります。

于 2009-04-09T21:18:06.027 に答える
0

あなたの例は、データベースがテーブル全体をロックした場合にのみ問題になります。データベースがそれを行っている場合...実行:)

于 2009-04-09T21:10:25.813 に答える