データベースのロックとは、トランザクションを競合させないようにするためのDBMS(データベースシステム)の仕組みです。
ロックがあるおかげで、トランザクションのACID特性が保たれています。
トランザクションのACID特性が知りたい方は、【データベースの基本】トランザクションのACID特定を読んでみてください!
また、ロックのせいでデッドロックやライブロックと呼ばれる困った問題も起きます。
デッドロックやライブロックもきちんと理解して対処すれば解決できます。
なので、基本をしっかり理解していきましょう!
データベースのロックとは
データベースのロックとは、操作中のデータを保護して他のユーザから操作できなくすることです。
言い換えるとロックは文字通り、データをロックすることです。
なぜ、データをロックするのかと思いませんか?
複数のユーザーがデータベースを操作するとき、ロックがないと間違ったデータを取得したり、生成してしまうからです。
ユーザが1人の時と、複数の時のデータベースの動きを把握すると理解できるようになります!
1人のユーザがデータベースを利用する時
データベースへのアクセスは常に直列になっているため、トランザクションの競合が発生することはないです。
複数のユーザがデータベースを利用する時
複数のユーザがデータベースを利用する時は、トランザクションの競合が発生することがあります。
同じデータに対して2回の+100の処理を行っています。そのため、最後には+200なるはずです。
しかし、2人のユーザーが同時に+100を行った時に、前の処理を上書きして+100になることがあります。
データをロックすることで、うさぎのトランザクションは失敗します。
くまなつのトランザクションが終わってから、うさぎのトランザクションは開始されます。
それによって+100、+100になり、最後には+200になります。
トランザクションの競合が発生しないので、複数のユーザーで同じデータベースを利用しても、データが正しくなります。
ロックの単位
ロックの単位には行、テーブル、データベース全体があります。
- 行
- テーブル
- データベース全体
行単位のロックが一般的です。トランザクションに使用するデータを1つずつロックします。
一度にたくさんのデータをロックする必要がある時は、効率が悪くなります。
テーブル単位のロックは、トランザクションに使用するデータが多い時に利用します。
1000行を1つずつロックするよりも、テーブルごとロックした方が効率的!という考えです。
テーブルがロックされるので、他のトランザクションはロックされたテーブルを操作することができなくなります。
データベース全体のロックはメンテナンス時などに利用します。
デッドロックとは
デッドロックとは、複数のユーザが同じデータをロックしようとすることで、トランザクションを完了できなくなる状態です。
複数のユーザと同じデータをロックするというポイントが重要です。
処理の流れは以下のようになります。
- ①くまなつはデータAをロックします
- ②うさぎはデータBロックします
- ③くまなつはデータBがロック解除されるのを待ちます
- ④うさぎはデータAがロック解除されるのを待ちます
- デッドロック発生!互いに、トランザクションが完了できない!
デッドロックの解決策
トランザクションのロック順序を同じにすることです。
今回の例の場合は、データAをロックして、データBをロックするというロック順序にすることでデッドロックを防げます。
万が一デッドロックが発生した場合は、データベースの管理者がどちらかのトランザクションを終了させ、データを戻します。
ライブロックとは
ライブロックとは、ロックしたいデータが常に利用中でトランザクションが完了できない状態のことです。
ずっと割り込みされている状態に近いです!
くまなつはテーブルAのデータ100件欲しいです。
処理の流れは以下のようになります。
- くまなつはテーブルAのデータ100件欲しいです。100件まとめてロックしようとします。
- うさぎがテーブルAのデータをロックします。処理をしてロックを解除します。
- きつねがテーブルAのデータをロックします。処理をしてロックを解除します。
- うさぎがテーブルAのデータをロックします。処理をしてロックを解除します。
- ライブロック発生!くまなつは必要なデータが常にロックされているのでトランザクションを完了できないです。
ライブロックの解決策
処理待ちのトランザクションに優先番号をつけて、一定時間待ったら番号を減らしていきます。
そうすると、優先度が上がり、トランザクションを実行することができます。