都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

デッドロックについて説明してみる - その 1 ( 一回で終わるかもしれないけど、その 1 にしてみた ) -

 近所の近くで少し早起きして、記事書きます。いつもより早起きするのもいいですね(^^♪
 f:id:koogucc11:20161012074234j:plain

 最近、デッドロックしている人 ( 作業に行き詰まるわけではなく、SQL Server のほうですw ) が多いので、デッドロックのおさらいしてみましょう。デッドロックとは、

デッドロック (英: deadlock) とは、特に計算機科学において、2つ以上のスレッドあるいはプロセスなどの処理単位が互いの処理終了を待ち、結果としてどの処理も先に進めなくなってしまうことを言う。

 早速、SQL Server Management Studio でデッドロックの実験をしてみましょう。データベースは AdventureWorks で、テーブルは Production.Product を使用します。下記の二つのクエリを SQL Server Management Studio で実行させてみましょう。

  • クエリ 1
    DECLARE @Error_Message  NVARCHAR(MAX);
    DECLARE @Error_Severity INT;
    DECLARE @Error_State    INT;
    
    WHILE 0 = 0
    BEGIN
        BEGIN TRY
            BEGIN TRAN
            -- ProductID = 2 のデータを更新する。
            UPDATE 
                Production.Product
            SET Name = N'Bearing Ball' 
            WHERE 
                ProductID = 2 
    
            -- ProductID = 1 のデータを更新する。
            UPDATE 
                Production.Product
            SET Name = N'Adjustable Race'
            WHERE 
                ProductID = 1 
            COMMIT TRAN
        END TRY
    
        -- 例外をキャッチしたら、メッセージを出力して処理を終了する。
        BEGIN CATCH
            SET @Error_Message  = ERROR_MESSAGE();
            SET @Error_Severity = ERROR_SEVERITY();
            SET @Error_State    = ERROR_STATE();
            RAISERROR(@Error_Message, @Error_Severity, @Error_State);
            BREAK;
        END CATCH
    END
    

  • クエリ 2
    DECLARE @Error_Message  NVARCHAR(MAX);
    DECLARE @Error_Severity INT;
    DECLARE @Error_State    INT;
    
    WHILE 0 = 0
    BEGIN
        BEGIN TRY
            BEGIN TRAN 
            -- ProductID = 1 のデータを更新する。
            UPDATE 
                Production.Product
            SET Name = N'Adjustable Race'
            WHERE 
                ProductID = 1 
    
            -- ProductID = 2 のデータを更新する。
            UPDATE 
                Production.Product
            SET Name = N'Bearing Ball' 
            WHERE 
                ProductID = 2 
    
            COMMIT TRAN
        END TRY
    
        -- 例外をキャッチしたら、メッセージを出力して処理を終了する。	
        BEGIN CATCH
            SET @Error_Message  = ERROR_MESSAGE();
            SET @Error_Severity = ERROR_SEVERITY();
            SET @Error_State    = ERROR_STATE();
            RAISERROR(@Error_Message, @Error_Severity, @Error_State);
            BREAK;
        END CATCH
    END
    

 クエリ 1 がデッドロックにより処理が終了しました。
f:id:koogucc11:20161012075718p:plain
-
 デッドロックが発生するまでのフローは下記の通りです。

f:id:koogucc11:20161012082404p:plain

 このようなケースでは対処方法は非常に簡単で、クエリ 1 および クエリ 2 のレコードの更新順番 ( 例:ProcuctID = 1 を更新してから、ProcuctID = 2 を更新する。 ) を下図のように同一にします。( ブロッキングは発生します。 )
f:id:koogucc11:20161012083905p:plain

その 1 だけでは終わらなそうです。その 2 からは身の回りで発生したデッドロックの事例とその説明をしたいと思います。

 Lenovo YOGA BOOK 用のケースがちらほら。

 明らかに対応していなさそうなものもあったりする。

 Lenovo YOGA BOOK はよ。
f:id:koogucc11:20161011222010p:plain

 こんな使い方もあるのか。これは思いつかなかった。
f:id:koogucc11:20161011222050p:plain

 Halo キーボード早く試したい。
f:id:koogucc11:20161011222141p:plain

 ヒンジは相変わらずカッコイイ。
f:id:koogucc11:20161011222207p:plain