まず各排他制御の方式について簡単に整理。
悲観的ロックとは
更新対象のデータを取得する際にロックをかけることで、他のトランザクションからは更新されないようにする方式。
更新が終ってから他の更新を開始することで整合性を担保する。
・更新のロックはRDBMSの"SELECT 〜 FOR UPDATE"を利用して実現される。
楽観的ロックとは
更新対象のデータがデータ取得時と同じ状態であることを確認してから更新する方式。
同じ状態でなければ、エラーを発生させデータの整合性を担保する。
・データがデータ取得時と同じ状態であることの確認は、テーブルにバージョン管理のためのカラムを追加することで実現する。
排他制御に関しては、以下の記事が超分かりやすかったです。
https://qiita.com/NagaokaKenichi/items/73040df85b7bd4e9ecfc
Railsでの実現方法
楽観的ロック
・lock_versionというカラムを追加するだけでok。(defaultは0にする必要がある)
このカラムを追加すると、更新対象のデータがデータ取得時と同じ状態かどうかを
lock_versionの値によって判断し、同じ状態でなかった時にrailsが例外を発生させてくれる。
悲観的ロック
・データ取得時にlockメソッドをつける。
こうすることで、SELECT 〜 FOR UPDATEが発行され他のトランズアクションからのupdate
をロックしてくれる。
ex) books.nameを更新する処理の場合。
Book.transaction do
book = Book.lock.find(n)
book.update!(name: '化学の新研究')
end