2026年1月27日火曜日

SQL Server ロックとブロッキングの仕組み|ロックの種類・ブロッキング・デッドロック対策

ロックとブロッキングの仕組みを理解しよう

SQL Serverでは、データの整合性を守るためにトランザクション中にロック(Lock)が発生します。
しかしロックが過剰に長く保持されると、他のセッションが待機状態に入り、ブロッキング(Blocking)デッドロック(Deadlock)が発生します。
本記事では、ロックの種類や仕組み、監視と解消方法を実務的に解説します。

目次

ロックの基本概念と役割

ロックは、同時実行される複数のトランザクションがデータを破壊しないように制御する仕組みです。
SQL Serverは、トランザクション整合性を保証するために自動的にロックを取得・解放します。

  • Shared Lock(S): 読み取り専用。複数セッションで共有可。
  • Exclusive Lock(X): 更新専用。他トランザクションのアクセスを遮断。
  • Update Lock(U): 読み取り後に更新予定の行に付与。

ロックは「行」「ページ」「テーブル」単位で取得され、一定条件を満たすとより大きな粒度へ昇格します。これをロックエスカレーションと呼びます。

ロックの種類と粒度(行・ページ・テーブル)

ロック粒度対象特徴
行ロック(Row Lock)単一行最も細かい単位で高い並行性を確保
ページロック(Page Lock)8KBのデータページ中間レベルの性能と整合性のバランス
テーブルロック(Table Lock)全テーブル一括操作に適するがブロッキングリスクが高い

ブロッキングの発生要因と確認方法

ブロッキングは、同じリソースに対して異なるトランザクションが同時アクセスしたときに発生します。
SQL Serverでは、ロックを取得したセッションが完了するまで他のセッションが待機します。

以下のクエリでブロッキング状況を確認できます。

SELECT 
    r.session_id, 
    r.blocking_session_id, 
    r.status, 
    t.text AS running_sql
FROM sys.dm_exec_requests r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.blocking_session_id <> 0;

blocking_session_idが示すセッションが、他のセッションをブロックしています。

デッドロックの仕組みと回避策

デッドロックとは、2つ以上のトランザクションが互いにロックを待ち合う状態です。
SQL Serverは自動的にデッドロックを検出し、どちらか一方をロールバックします。

BEGIN TRY
    BEGIN TRAN;
        UPDATE TableA SET Col1 = 1 WHERE ID = 1;
        UPDATE TableB SET Col1 = 2 WHERE ID = 2;
    COMMIT TRAN;
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK TRAN;
    PRINT 'デッドロックが発生したため、トランザクションをロールバックしました。';
END CATCH;

デッドロックを防ぐには、アクセス順序を統一し、トランザクションを短く保つことが有効です。

実務でのロック監視とチューニング方法

  • sys.dm_tran_locks: 現在のロック状況を確認
  • sys.dm_exec_requests: 実行中のSQLとブロック情報を取得
  • sp_who2: セッションと待機状態の概要を把握
  • sys.dm_os_waiting_tasks: 待機タイプごとの詳細分析

特に待機タイプが LCK_M_S(共有ロック)や LCK_M_X(排他ロック)で長時間続いている場合は、処理設計の見直しが必要です。

ヒント句と分離レベルによる制御例

SQL Serverでは、ロック動作を制御するためにヒント句や分離レベルを指定できます。

-- NOLOCK(READ UNCOMMITTED相当)を利用してロックを回避
SELECT * FROM dbo.Sales WITH (NOLOCK);

-- ROWLOCK/UPDLOCKヒントで制御
SELECT * FROM dbo.Inventory WITH (ROWLOCK, UPDLOCK);

また、分離レベルを設定することでロックの取得範囲を制御可能です。

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN TRAN;
    SELECT * FROM dbo.Orders;
COMMIT TRAN;

まとめ:ロックを理解して安定した運用を実現

ロックはデータの整合性を守るために欠かせない仕組みですが、過剰なロックはパフォーマンスを阻害します。
ブロッキングやデッドロックは、設計・アクセス順・トランザクション粒度で大きく改善できます。
適切な分離レベル・ヒント句・短いトランザクションを意識し、監視を継続することで安定した運用が可能になります。

参考リンク(公式ドキュメント)

SQL Server 解説用イメージ

0 件のコメント:

コメントを投稿