▼ 2010/08/17(火) 楽観的ロックと悲観的ロック
2010/08/17 14:41 【研究課題】
音楽の話題ではないよ。
railsで、DBのレコードロックについてちょっと調べた。
ruby on railsが提供するレコードロックは楽観的ロックと悲観的ロックの2種類がある。
この、いかにも直訳調な名称もどうかと思うけど、たいがい二つ並べて解説されているのでなんかこうよく似たものと思われがち。ところがこの二つ、実は使いどころがまったく違うシロモノだったって話。
悲観的ロックは、レコードを読み込むときかける形式のロックで、要するに「これからこのレコードをいろいろいじるのでほかのやつらは触るなよ」と言う宣言。実装はDBエンジンに依存している。MySQLなりPostegrasなり、主要なDBエンジンはたいてい対応しているはず。
楽観的ロックは、レコードを書き込むときに問い合わせる形式のロックで、要するに「とりあえず変更したレコードを手元に持っているけどほんとにこれ書き込んでいいのかな」という確認。実装はActiveRecordが担う。テーブルにlock_versionという項目を作っておく必要がある。詳細はぐぐってくれ。
理解するポイントは、実はロックをかけるタイミングではなく、ロックをはずすタイミングがあるかないか。だと思う。
悲観的ロックっていうのは、ロックをかけた人が責任持ってロックをはずす必要がある。saveなりなんなりを契機にしてDBエンジンがちゃんとロック解除の世話を見てくれるのでユーザはあんまり意識しなくてすんでいるけど、確実に解除はしておかないと、つまりデッドロックに陥ってしまう。
対して、楽観的ロックにはそもそもロックをかけるという概念が薄い。railsでいえば、saveするたびにlock_versionがインクリメントされる。もし、あるレコードをsaveしたときに、そのレコードをfindしてきたときのlock_versionと違っていたらエラーをraiseするのが楽観的ロック。
railsでロックをかけるという場合、これはもう、ほとんどWebシステムで、editで画面を作るときにfindされupdateをpostされたときにsaveされることになる。findの時点とpostの時点でセッションが違うのだ。
悲観的ロックとは、バッチ処理などで一連のトランザクションが進行する間だけレコードの整合性を保障するための仕組みである。ひとつのプロセスなりスレッドなりセッションなりで処理が完結する場合に有効な戦略ということ。
findの時点とsaveの時点でセッションが違うと、システムが責任もって処理を完結させることができない可能性が出てくる。たとえばeditで画面を表示(つまりfindでレコードをロード)したあとブラウザを閉じちゃって、ついにupdateを呼び出さなかった場合、ロックを解除する契機がなくなってしまう。
これが楽観的ロックだと、saveするときにだけ上書きできるかどうか確認する。楽観的ロックであれば、findとsaveの同期を取る必要がない。saveの時だけ判断すればいいのだ。
てなわけで、結局railsではほとんど楽観的ロックしか、出番がないってことですな。
railsで、DBのレコードロックについてちょっと調べた。
ruby on railsが提供するレコードロックは楽観的ロックと悲観的ロックの2種類がある。
この、いかにも直訳調な名称もどうかと思うけど、たいがい二つ並べて解説されているのでなんかこうよく似たものと思われがち。ところがこの二つ、実は使いどころがまったく違うシロモノだったって話。
悲観的ロックは、レコードを読み込むときかける形式のロックで、要するに「これからこのレコードをいろいろいじるのでほかのやつらは触るなよ」と言う宣言。実装はDBエンジンに依存している。MySQLなりPostegrasなり、主要なDBエンジンはたいてい対応しているはず。
楽観的ロックは、レコードを書き込むときに問い合わせる形式のロックで、要するに「とりあえず変更したレコードを手元に持っているけどほんとにこれ書き込んでいいのかな」という確認。実装はActiveRecordが担う。テーブルにlock_versionという項目を作っておく必要がある。詳細はぐぐってくれ。
理解するポイントは、実はロックをかけるタイミングではなく、ロックをはずすタイミングがあるかないか。だと思う。
悲観的ロックっていうのは、ロックをかけた人が責任持ってロックをはずす必要がある。saveなりなんなりを契機にしてDBエンジンがちゃんとロック解除の世話を見てくれるのでユーザはあんまり意識しなくてすんでいるけど、確実に解除はしておかないと、つまりデッドロックに陥ってしまう。
対して、楽観的ロックにはそもそもロックをかけるという概念が薄い。railsでいえば、saveするたびにlock_versionがインクリメントされる。もし、あるレコードをsaveしたときに、そのレコードをfindしてきたときのlock_versionと違っていたらエラーをraiseするのが楽観的ロック。
railsでロックをかけるという場合、これはもう、ほとんどWebシステムで、editで画面を作るときにfindされupdateをpostされたときにsaveされることになる。findの時点とpostの時点でセッションが違うのだ。
悲観的ロックとは、バッチ処理などで一連のトランザクションが進行する間だけレコードの整合性を保障するための仕組みである。ひとつのプロセスなりスレッドなりセッションなりで処理が完結する場合に有効な戦略ということ。
findの時点とsaveの時点でセッションが違うと、システムが責任もって処理を完結させることができない可能性が出てくる。たとえばeditで画面を表示(つまりfindでレコードをロード)したあとブラウザを閉じちゃって、ついにupdateを呼び出さなかった場合、ロックを解除する契機がなくなってしまう。
これが楽観的ロックだと、saveするときにだけ上書きできるかどうか確認する。楽観的ロックであれば、findとsaveの同期を取る必要がない。saveの時だけ判断すればいいのだ。
てなわけで、結局railsではほとんど楽観的ロックしか、出番がないってことですな。
- TB-URL http://snjx.info/diary/adiary.cgi/snjx/041/tb/