行ロックとは
行ロックとは、テーブルの同一レコードに対して、複数同時に更新できないように制限する仕組みのことです。
Ruby on RailsのActiveRecordには2種類のロック方法があります。
- 楽観的ロック(Rails依存)
- 悲観的ロック(DBMS依存)
それぞれの違いや使い方について解説していきたいと思います。
楽観的ロック
楽観的ロックとは、DBMSの機能に頼らずロックバージョンをレコードに保存しておくことで、取得時と変更時にロックバージョンに変更がないか確認し、変更があった場合は例外を発生させる方法です。
- ロックするタイミング
- データ更新時
- データを複数同時に取得することができるが、途中で更新されていた場合は、更新できない
- 仕組み
- テーブルにlock_versionフィールドを追加する
- lock_versionが書き換わっていたらActiveRecord::StaleObjectErrorを発生させる
- 使い方
- テーブルにlock_versionを追加するだけ
# db/migrate/201006091552_create_accounts.rb
class CreateAccounts < ActiveRecord::Migration
def self.up
create_table :accounts do |t|
t.float :balance, :null => false, :default => 0
t.integer :lock_version, :default => 0
end
end
def self.down
drop_table :accounts
end
end
悲観的ロック
悲観的ロックとは、DBMSの行ロック機能(SELECT FOR UPDATE句)を利用して、並行した更新作業を制限する方法です。
ロックはレコード取得時にかかるので、同時にレコードを取得しようとした場合は他方がロック解除になるまで待機するため、同時に同じレコードを取得できないようになります。
そのため楽観的ロックよりも、より厳格ですが、利用できるDBMSはPostgresかMySQLに制限されています。
- ロックするタイミング
- データ取得時
- すでにロックがかかっている行の取得が制限され、ロック解除されるまで待機する
- 仕組み
- SELECT FOR UPDATE句を使いDBMS側で行ロックする
- PostgreSQL & MySQLのみ
- 使い方
- Account.find(:first, :lock => true)
- a = Account.find(:first).lock!
# With lock paramater
account1 = Account.find(1, :lock => true)
# or With lock! Method
account2 = Account.find(1)
account2.lock!
このエントリーに対するコメント
日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)
- トラックバック
「いいね!」で応援よろしくお願いします!