データベースにおけるロックについて

データベースの勉強中ロックについての理解があいまいだと思ったのでこの記事を書きます。

ロックとは

同じデータを複数人が同時に変更できないようにすることを「ロック」といいます。
そのため、あるトランザクションがデータを変更しているときロックがかかっていると,他のトランザクションは同じデータを変更することができなくなります。

なぜ必要なのか?

データ変更を複数同時に行う際に問題が起きないようにするためです。

ロックが存在しない場合

ロックが存在しない場合を考えてみましょう。
Xというデータに対して、AとBという二つのトランザクションが同時に1を加える変更をしようとしています。
この場合、AとBの両トランザクションが終了した時点でXはX+2の状態である必要があります。
ですが、ロックが存在しない場合2つのトランザクションが終了した時点でのXはX+1である可能性があります。
奇妙なことに思えますが、下記の手順で処理が行われると十分に起こり得ます。

  • AとBがともにXを参照する
  • AとBがともにXに1を加える
  • AがXX+1に変更する
  • BがX+1X+1に変更する

ロックが存在する場合

ロックが存在する場合はそのような事は起こりません。
ロックが存在する場合、AとBが同時にXへの変更を実行しようとしたときに、どちらかのトランザクションが優先して実行されます。もう片方のトランザクションは、前のトランザクションが終了するまで実行を待機することになります。
この場合、下記の手順で処理が実行されます。

  • AがXを参照する
  • Aが1を加える
  • AがXX+1に変更する
  • BがX+1を参照する
  • Bが1を加える
  • BがX+1X+2に変更する

ロックの種類

ロックには共有ロックと占有ロックの二つの種類があります。

共有ロック

共有ロックはロック中も別のトランザクションから読み取りが許可されているロックです。
許可されているのは読み取りのみで、変更や削除を行うことはできません。その場合待機状態になります。

占有ロック

占有ロックでは読み込みも含めてすべてのアクセスが遮断されます。他のすべてのトランザクションは待機状態になります。

デッドロック

ロックは便利な仕組みですが、大規模なデータベースでは問題を引き起こす場合もあります。その一つがデッドロックです。
あるトランザクションが変更しようとしているデータがロック状態にある時そのトランザクションはロックが解除されるまで待機状態になります。この時2つのトランザクションがお互いに相手を待つ待機状態になり処理が進まなくなることをデッドロックといいます。デッドロックは以下のような状況で起こりえます。

  • トランザクションAがデータ1に対してロックを取得し、次にデータ2に対するロックを要求する。
  • 同時に、トランザクションBがデータ2に対してロックを取得し、次にデータ1に対するロックを要求する。
  • この結果、トランザクションAとBがお互いにロック解除を待つ状態になり、どちらも処理が進まなくなる。