ITの教科書検索
入門読了 約9分

排他制御とデッドロックとは ― ロック待ちと解消

排他制御は、同時更新による矛盾を防ぐために、ロックで後から来た処理を待たせる仕組みです。専有ロックと共有ロックの組み合わせ、デッドロックが起きる理由と防ぎ方が分かります。

目次
  1. 排他制御とは
  2. 専有ロックと共有ロックの両立性
  3. デッドロックが起きる仕組み
  4. 検知と解消(ロールバック)
  5. 練習問題

排他制御は、ロックの組み合わせで待たせるかどうかを決める

排他制御とは、複数のトランザクションが同時に同じデータを更新しても、矛盾が起きないようにする仕組みです。後から来た側を待たせるかどうかは、2つのトランザクションが使うロックの種類の組み合わせで決まります。待たせ方によっては、互いに待ち合って動けなくなるデッドロックも起きます。

専有ロック(書き換えるときに取るロック)と共有ロック(読むときに取るロック)の基本と、ロックを取る範囲の大きさを表すロック粒度は、トランザクションとACID特性の記事で説明しています。

専有ロックと共有ロックの両立性

専有ロックと共有ロックには、同時に許可される組み合わせと、許可されない組み合わせがあります。同時に許可されるかどうかを、ロックの両立性と呼びます。次の図では、同じ1行のデータにトランザクションAが先にロックを取り、トランザクションBが後から要求する場面で、4つの組み合わせを比べます。

共有ロック × 共有ロックA:共有ロックで読むロック取得済みB:共有ロックで読むロック取得済み同じ行を要求両方同時に許可される共有ロック × 専有ロックA:共有ロックで読むロック取得済みB:専有ロックを要求Aの解放まで待つ同じ行を要求Bは待たされる専有ロック × 共有ロックA:専有ロックで書くロック取得済みB:共有ロックを要求Aの解放まで待つ同じ行を要求Bは待たされる専有ロック × 専有ロックA:専有ロックで書くロック取得済みB:専有ロックを要求Aの解放まで待つ同じ行を要求Bは待たされる
同じ1行のデータに、トランザクションAが先にロックを取り、トランザクションBが後から要求する場面です。共有ロックどうしだけが同時に許可されます。専有ロックが一方でも絡むと、Bは待たされます。

共有ロックどうしは、同時に許可されます。どちらも読むだけの処理のため、同時に進めても矛盾しません。一方、専有ロックが関わる組み合わせは、同時に許可されません。先にロックを持つ側の処理が終わるまで、もう一方は待たされます。同時に動くトランザクションに、ほかの変更がどこまで見えるかの段階は、分離レベルの記事で説明しています。

デッドロックは、互いのロックの解放を待ち合う状態

デッドロックとは、複数のトランザクションが、互いの持つロックの解放を待ち合い、どちらも先に進めなくなる状態です。原因は、それぞれのトランザクションがロックを取る順番の食い違いにあります。例えば、注文表と在庫表という2つの表を、トランザクションAとBがそれぞれ更新する場面を考えます。

Aが注文表から在庫表の順でロックを取り、Bが在庫表から注文表の順でロックを取ると、互いに相手がロックした表を取りにいく形になります。次の図で、ロックを取る順番を切り替えると、デッドロックになる場合とならない場合を確かめられます。

↓ 時系列(上から下へ)トランザクションA(注文表→在庫表の順)トランザクションB(在庫表→注文表の順)注文表に専有ロックロックを取得在庫表のロックを要求在庫表はBが保持中→待つデッドロックとして検知片方がロールバックされる在庫表に専有ロックロックを取得注文表のロックを要求注文表はAが保持中→待つデッドロックとして検知片方がロールバックされる互いに待つ互いの解放を待ち合い、デッドロックになる
AとBが逆の順でロックを取りにいくと、互いが相手の持つロックの解放を待ち合い、デッドロックになります。

ロックを取る順番が食い違うと、Aは在庫表の解放を待ち、Bは注文表の解放を待つので、どちらも終わりません。順番をそろえると、Bは単にAの完了を待つだけになり、デッドロックは起きません。

デッドロックは、検知後にDBMSが一方をロールバックして解消する

デッドロックは、待っているだけでは解消しません。MySQLやPostgreSQLは、デッドロックの状態を検知すると、関係するトランザクションの一方を自動的にロールバックします。どちらをロールバックするかはDBMSが決めるため、アプリケーションの側では選べません。

ロールバックされたトランザクションは、もう一度やり直す必要があります。そのため、アプリケーションは、自分の側がロールバックされる場合に備えて作る必要があります。デッドロックの危険を減らすには、すべてのトランザクションでロックを取る順番をそろえる対策が有効です。先にロックを取るやり方と、ロックを取らずに更新の時点で衝突を見つけるやり方の違いは、楽観ロックと悲観ロックの記事で比べています。

参考にした資料

練習問題(全5問)

Q1共有ロックを持つデータに、別のトランザクションが共有ロックを要求すると、どうなる?
Q2専有ロックを持つデータに、別のトランザクションが共有ロックを要求すると、どうなる?
Q3デッドロックの説明として最も適切なものはどれ?
Q4デッドロックの危険を減らす対策として適切なものはどれ?
Q5DBMSがデッドロックを検知すると、一般的に何が起こる?

選んでから「採点する」を押すと、解説つきで答え合わせができます。

関連記事

おすすめの本 PR

セキュリティとデータベースは、基本情報技術者試験の対策本でまとめて学べます。

目的別の本の選び方を見る

データベースの記事を続けて読む

データベース 全36本中28本目