ActiveRecordで行ロックをかける方法 このエントリをはてなブックマークに登録

2010年06月10日

func09func09 /

行ロックとは

行ロックとは、テーブルの同一レコードに対して、複数同時に更新できないように制限する仕組みのことです。

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!
  1. メモからはじめる情報共有 DocBase 無料トライアルを開始
  2. DocBase 資料をダウンロード

「いいね!」で応援よろしくお願いします!

このエントリーに対するコメント

コメントはまだありません。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


トラックバック

we use!!Ruby on RailsAmazon Web Services

このページの先頭へ