5

分離レベルのT1 と T2 の 2 つのトランザクションがSERIALIZABLEあります (デフォルトの分離レベルだと思いますREAD COMMITTEDが、問題ではありません)。

トランザクション T1 はSELECT、次にWAITFOR2 秒、次にを実行しSELECTます。

トランザクション T2 はUPDATE、T1 が読み取ったデータに対して実行されます。

デッドロックが発生します。トランザクション T2 が T1 の終了を待たないのはなぜですか?

T1 にREPEATABLE READ分離レベルがある場合、すべて問題ありません。つまり、幻の行が発生します。SERIALIZABLE分離レベルを まで上げると、T2 は T1 の終了を待つと思いました。

これは私の大学の演習の一部です。分離レベルが正しくなく、分離レベルが正しくてもこれらの影響がない 2 つの並列トランザクションで負の影響を示す必要があります。

コードは次のとおりです。残念ながら、フィールドの名前はポーランド語です。

T1:

MRを使用してください。

IMPLICIT_TRANSACTIONS をオフに設定します。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

取引を開始します。

-- 1. ザピタニエ
選択する
    www.IdSamochodu、s.Model、s.Marka、s.NrRejestracyjny、o.PESEL、o.Nazwisko、o.Imie、o.NrTelefonu
から
    WizytyWWarsztacie www
加入
    サモチの
    ON s.IdSamochodu = www.IdSamochodu
加入
    おそびを
    ON o.PESEL = s.PESEL
どこ
    www.[ステータス] = 'gotowy_do_odbioru'
ORDER BY www.IdSamochodu ASC
;

WAITFOR DELAY '00:00:02';

-- 2. ザピタニエ
選択する
    u.IdSamochodu、tu.Nazwa、tu.Opis、u.Oplata
から
    うするぎう
加入
    TypeyUslug tu
    ON tu.IdTypuUslugi = u.IdTypuUslugi
加入
    WizytyWWarsztacie www
    ON www.IdSamochodu = u.IdSamochodu AND
        www.DataOd = u.DataOd
どこ
    www.[ステータス] = 'gotowy_do_odbioru'
ORDER BY u.IdSamochodu ASC, u.Oplata DESC
;

専念;

T2:

MRを使用してください。

IMPLICIT_TRANSACTIONS をオフに設定します。
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

取引を開始します。

アップデート
    ウスルギ
設定
    [ステータス] = 'wykonano'
どこ
    IdUslugi = 2
;

アップデート
    www
設定
    www.[ステータス] = 'gotowy_do_odbioru'
から
    WizytyWWarsztacie www
どこ
    www.[ステータス] = 'wykonywanie_usług' AND
    存在する (
        選択 1
        から
            うするぎう
        どこ
            u.IdSamochodu = www.IdSamochodu AND
            u.DataOd = www.DataOd AND
            u.[ステータス] = 'wykonano'
        GROUP BY u.IdSamochodu、u.DataOd
        HAVING COUNT(u.IdUslugi) = (
            選択する
                COUNT(u2.IdUslugi)
            から
                ウスルギu2
            どこ
                u2.IdSamochodu = www.IdSamochodu AND
                u2.DataOd = www.DataOd
            GROUP BY u2.IdSamochodu、u2.DataOd
        )
    )
;

専念;

私は SQL Management Studio を使用しており、各トランザクションを異なるファイルに保存しています。T1 で F5 をクリックしてこれを実行し、T2 を含むファイルにすばやく切り替えて、もう一度 F5 を実行します。

mssql のデッドロックとロック メカニズムについて読みましたが、どうやら、このトピックをまだ理解していないようです。

SQL Server 2008 R2 (.Net 2.0 アプリケーション) でのデッドロックの問題

選択/更新または複数の選択の間で SQL Server がデッドロックする

SELECT/UPDATE でのデッドロック

http://msdn.microsoft.com/en-us/library/ms173763(v=sql.105).aspx

http://www.sql-server-performance.com/2004/advanced-sql-locking/

編集

T2 の最初の UPDATE ステートメントが問題の原因であることがわかりました。なぜですか?

4

4 に答える 4

6

デッドロックのトラブルシューティングは、デッドロック グラフを取得することから始まります。これは、関連するトランザクションとリソースに関する関連情報を伝える xml ドキュメントです。プロファイラー、拡張イベント、またはイベント通知を介して取得できます (他の方法があると確信していますが、今のところはこれで十分です)。グラフを取得したら、それを調べて、各トランザクションがどのリソースに対してどのタイプのロックを持っていたかを確認します。そこからどこへ行くかは、グラフで何が起こっているかに大きく依存するので、そこでやめます。結論: デッドロック グラフを取得し、詳細を調べます。

余談ですが、いずれかのトランザクションがデッドロックを「引き起こしている」と言うのは、やや誤解を招きます。デッドロックに関係するすべてのトランザクションは、デッドロック状態を引き起こすために必要だったので、どちらにも過失はありません。

于 2013-01-12T21:48:25.157 に答える
1

SQL Managmenet Studioで問題が発生しました(プロファイラーが機能しませんでした)が、最終的にデッドロックグラフを取得しました。この記事は私にとって役に立ちました。

デッドロック

このグラフを理解するには、ロックのメカニズムと記号について学ぶ必要がありました。ここでは非常に明確に説明されている
と思います。

さて、私がこれらすべてのことを知っているとき、デッドロックの原因は非常に明白です。
説明した状況のシーケンス図を作成しました。

シーケンス図

前に書いたように、トランザクションT2から最初のUPDATEステートメントを削除しても、デッドロックは発生しません。

この状況では、T2はインデックスのロックを取得しないため、pk_uslugiトランザクションT1からの2番目のSELECTステートメントが正常に実行され、インデックスのpk_wizytywwarsztacieロックが解除されます。その後、T2も終了します。

于 2013-01-13T22:26:03.407 に答える
0

問題はこれである可能性があります:

  1. T1 Select S-lock は行をロックします
  2. T2 Update は行を U ロックします (成功)
  3. T2 Update は行を X ロックします (待機し、ロックはキューに入れられます)
  4. T2 は S ロックを再試行しますが、S ロックはキューに入れられた X ロックと互換性がありません。

SQL Server のロックはキューに入れられます。キューの先頭が待機すると、その後ろにある他のすべても待機します。

実際、これが原因かどうかは完全にはわかりません。なぜなら、同じ問題REPEATABLE READ. それが役立つことを願って、私はまだこのアイデアを投稿しています。

于 2013-01-12T21:59:54.020 に答える