SQL ロックの種類(共有ロック/排他ロック)

SQLのロックの種類についてです。

ロック ロックとは
  共有ロック
  排他ロック
  デッドロックとは
データ取得→更新 楽観的ロック(アプリ側で制御する)
  悲観的ロック(DB側で制御する(select-for update))

ロックとは

データを処理中に他ユーザーに更新等の処理をさせないという仕組みです。排他制御とも言います。
ロックの種類として共有ロック、排他ロックがあります。
ロックの範囲もテーブル全体にかける、特定の行にかける等種類があります。

 

共有ロック

ユーザ1が行001を読み込んでいる間は、ユーザ2は行001を読み込みはできますが、更新はできません。
→共有ロックです。読み取りロックとも言います。

ユーザ2が行001をselectした時点でも共有ロックがかかります。
→複数ユーザが行001に対して同時にかけることができます。

 

排他ロック

ユーザ1が行001を書き込んでいる間は、ユーザ2は行001を読み込み、書き込みともにできません。
→排他ロックです。占有ロックとも言います。

ユーザ2は行001に対して共有ロックも排他ロックもかけることはできません。待ちの状態になります。

 

デッドロックとは

ユーザ1が行001に対してを排他ロックをかけてupdate1を行いました。commitしていません。
ユーザ2が行002に対してを排他ロックをかけてupdate2を行いました。commitしていません。

ユーザ1が行002に対してをupdate3を行おうとしますが排他ロックがかかっていて待ちの状態になります。
ユーザ2が行001に対してをupdate4を行おうとしますが排他ロックがかかっていて待ちの状態になります。

この場合データベースの機能によってはデッドロックを検知して両者の更新を失敗させることができます。

 

楽観的ロック(アプリ側で制御する)

データを取得してデータ確認後にデータ更新をする処理がある場合、
データ取得時にロックを掛けず、データ更新時にアプリ側でデータ取得時点からデータが変更されていないかチェックしてから更新するやり方です。
変更されていた場合は更新しません。

データが変更されていないかチェックする項目として更新日時や専用のバージョン管理項目を使用します。
ロックの待ちは発生しません。

更新が少ない環境で使用します。

 

悲観的ロック(DB側で制御する(select-for update))

データを取得してデータ確認後にデータ更新をする処理がある場合、
データ取得時にDB側の機能であるSQL(select-for update)でロックを掛け、データ更新してロックを外します。

データが変更されていないかチェックする項目は不要です。
ロックの待ちが発生します。

更新が多い環境で使用します。

SQL select for updateのサンプル

参考
https://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%83%E3%82%AF_(%E6%83%85%E5%A0%B1%E5%B7%A5%E5%AD%A6)

関連の記事

SQL トランザクション分離レベルの概要

△上に戻る