目次
悲観ロックってなに?
悲観ロックとは、排他制御の代表的な方式の1つです。
排他制御とは共有資源に対して同時にアクセスしても問題なく動作できる制御のことをいいます。
交通機関で例えると、車が走る道路(交通資源)に信号機がない場合、事故が起こる危険性があります。そのため信号を設置して、事故が起きないように制御しています。
このように、道路に信号を設置して事故が起きないようにする制御と同じようなイメージです。
スポンサーリンク
排他制御をしていないとどうなるの?
排他制御は共有資源に対して同時にアクセスする可能性がある場合に使用します。
もし排他制御をしていないと下記のようなことが発生する可能性があります。
(1)共有資源に対して同時アクセス
ショッピングサイトに対して「Aさん」と「Bさん」が同時に同じ商品を購入します。
(2)共有資源に対してデータを読み取る
購入可能であるか確認するために「在庫テーブル」から「在庫数」を取得します。「在庫数」は"10"なので購入可能と判断されます。
(3)共有資源を更新する
在庫を取得してきた10から1減らして「Aさん」の購入を確定します。「在庫テーブル」の「在庫数」は"9"。
(4)共有資源を更新すると整合性が取れないデータになる
在庫を取得してきた10から1減らして「Bさん」の購入も確定します。「在庫テーブル」の「在庫数」は"9"。
このように排他制御をしていないと、在庫数が"8"ではなく"9"になってしまう可能性があるのです。
この問題を解消するのが排他制御です。
排他制御には様々な方法がありますが、有名な方式として楽観ロック(楽観的排他制御)と悲観ロック(悲観的排他制御)が存在します。
本記事では「悲観的な考え方の排他制御」である、悲観ロックについて紹介していきます。
スポンサーリンク
悲観ロックの流れ
悲観ロックは、同じデータを他者が頻繁に更新するという悲観的な考え方の排他制御です。具体的には、更新対象データを取得時にロックして他者が操作できないようにする方式。
悲観ロックの流れを具体的に説明していきます。
(1)共有資源に対して同時アクセス
ショッピングサイトに対して「Aさん」と「Bさん」が同時に同じ商品を購入します。
(2)共有資源に対してデータを読み取りロックする
購入可能であるか確認するために「在庫テーブル」から対象商品の「在庫数」を取得します。まずは「Aさん」がデータを取得します。この時、対象商品のデータをロックします。
(3)共有資源はロックされているので、読み取りできない
次に「Bさん」も「在庫テーブル」から対象商品の「在庫数」を取得しようとするが、対象商品のデータはロックされているので、読み取る事ができません。
そのため、ロックが解除されるまで待機します。
(4)共有資源を更新する
在庫を取得してきた10から1減らして「Aさん」の購入を確定します。「在庫テーブル」の「在庫数」は"9"。更新が完了したらロックを解除します。(コミット または ロールバックのタイミングで解除)
(5)再度、共有資源に対してデータを読み取りロックする
対象商品のデータのロックが解除されたので、「Bさん」がデータを取得します。この時、対象商品のデータをロックします。
(6)共有資源を更新する
在庫を取得してきた9から1減らして「Bさん」の購入を確定します。「在庫テーブル」の「在庫数」は"8"。更新が完了したらロックを解除します。(コミット または ロールバックのタイミングで解除)
このように悲観ロックを行うことで、データの整合性を保つことができます。
悲観ロックの実装方法は「SELECT 〜 FOR UPDATE」を利用して行うのが一般的です。「SELECT 〜 FOR UPDATE」はSELECT時に行ロックしてデータを更新、そしてコミットまたはロールバック時にロックを解除する方式です。