- PR -

DBのロックについて

投稿者投稿内容
SUNNYDAY
常連さん
会議室デビュー日: 2004/07/14
投稿数: 49
投稿日時: 2005-08-03 18:02
こんにちわ、いつもお世話になっております。
とても初歩的な質問で、申し訳ありません。
DBのロックについてなのですが、
楽観ロックと悲観ロックなのですが、
まず、前提としてDBのデータ更新を行おうとしている
ユーザーA、ユーザBがいるとして、

1、ユーザーA、ユーザーBともに、レコード1(同一レコード)を参照
2、ユーザーA、レコード1を更新
3、ユーザーB、レコード1を更新

という状況になった時、
楽観ロック(論理排他)では、ユーザーAが既にレコード1を更新しているため、
ユーザーBが参照しているレコード1は古いです、なので更新はできません
となり、悲観ロック(物理排他)では、どのようになるのでしょうか?
DBのロックについて、何か参考になるWEBページ等がありましたら
ご紹介ください。よろしくお願い致します。
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2005-08-03 18:08
ユーザーAがレコードを参照時に排他ロックを行う場合、ユーザーBがレコードを参照しようとした時点でロックが行われます。その後ユーザーAがレコードの更新を完了した後で、ユーザーBの処理はロックが解除され続きを行うことになります。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-08-04 14:40
まず、悲観的ロックも楽観的ロックもどちらも「論理的排他」です。両者の違いは、排他処理を
参照時に行うか更新時に行うかにあります。

悲観的ロックは、「一つのリソースを同時に更新することが頻繁にありうる」ことを前提に、
(更新のための)参照を行った時点でロックを掛けます。ロックの方法は、レコードにロック
フラグ(ロックユーザのIDを入れる場合もある)のフィールドを持たせ、参照時にそのフラグを
設定するのが一般的です。

一方楽観的ロックは、「一つのリソースを同時に更新することはほとんどない」ことを前提に、
更新時に排他チェックを行います。排他チェックの方法は、レコードにタイムスタンプの
フィールドを持たせ、参照時と更新時のフィールド値を比較するのが一般的です。

どちらを選択するかは要件しだいです。安全なのは悲観的ロックですが、実装は楽観的ロックの
方が簡単です。
SUNNYDAY
常連さん
会議室デビュー日: 2004/07/14
投稿数: 49
投稿日時: 2005-08-04 17:20
甕星さん、ukさんご回答ありがとうございました。
なるほど。
勉強になります。
最後に確認させてください。
悲観的ロック:select〜 for update
楽観的ロック:update
ということでよいでしょうか?


uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-08-04 19:22
引用:

SUNNYDAYさんの書き込み (2005-08-04 17:20) より:
最後に確認させてください。
悲観的ロック:select〜 for update
楽観的ロック:update
ということでよいでしょうか?


どのように読めばそのような結論になるのでしょうか。
というか、それだけだとどのような結論かわからないのですが。
SUNNYDAY
常連さん
会議室デビュー日: 2004/07/14
投稿数: 49
投稿日時: 2005-08-05 18:55
こんばんわ。
いつもお世話になっております。
すみません、私の解釈が間違っていたようで・・・

引用:

ukさんの書き込み (2005-08-04 19:22) より:
どのように読めばそのような結論になるのでしょうか。
というか、それだけだとどのような結論かわからないのですが。



引用:

悲観的ロックは、「一つのリソースを同時に更新することが頻繁にありうる」ことを前提に、
(更新のための)参照を行った時点でロックを掛けます。ロックの方法は、レコードにロック
フラグ(ロックユーザのIDを入れる場合もある)のフィールドを持たせ、参照時にそのフラグを
設定するのが一般的です。



「参照を行った時点でロックを掛ける」とのことだったので、
参照→更新であるselect〜for updateは、
悲観的ロックに当たる
(というか、悲観的ロックの実装可能という表現の方が正しいのでしょうか・・・)
のかと思ってしまいました。

引用:

一方楽観的ロックは、「一つのリソースを同時に更新することはほとんどない」ことを前提に、
更新時に排他チェックを行います。排他チェックの方法は、レコードにタイムスタンプの
フィールドを持たせ、参照時と更新時のフィールド値を比較するのが一般的です。



楽観的ロックは、更新時にロックを掛ける
とのことだったので、これはただのupdateは、
こちらにあたるのかと解釈してしまいました。。。
カーニー
ぬし
会議室デビュー日: 2003/09/04
投稿数: 358
お住まい・勤務地: 東京
投稿日時: 2005-08-05 19:20
引用:

ukさんの書き込み (2005-08-04 14:40) より:
悲観的ロックは、「一つのリソースを同時に更新することが頻繁にありうる」ことを前提に、
(更新のための)参照を行った時点でロックを掛けます。ロックの方法は、レコードにロック
フラグ(ロックユーザのIDを入れる場合もある)のフィールドを持たせ、参照時にそのフラグを
設定するのが一般的です。



DBMSの持つロック機能を用いるほうが一般的だと思うのですが・・・。
OracleでいうSELECT FOR UPDATEなど。

Webアプリで複数画面にまたがるトランザクションだと厳しいですけど。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-08-05 19:41
引用:

カーニーさんの書き込み (2005-08-05 19:20) より:
DBMSの持つロック機能を用いるほうが一般的だと思うのですが・・・。
OracleでいうSELECT FOR UPDATEなど。

Webアプリで複数画面にまたがるトランザクションだと厳しいですけど。


物理的ロックを使用する仕組みだと、コネクションを接続したまま処理をすることが前提に
なります。Webアプリケーションのようなステートレスな通信ではもちろん問題になりやすい
ですが、そうでなくても参照から更新までの時間が短くかつ保障できる、あるいはそもそも
更新処理自体が少なくてそのこと自体が問題になりにくい、などある程度限定した条件でないと
使いにくいと思います。

また、ロックされているリソースを次に参照しようとしたクライアントはロック待ちになってし
まうわけですが、それでいいのでしょうか。悲観的ロックや楽観的ロックのどちらにしようかと
考えるような要件であれば、ロックされていることを通知して欲しい場合が多いと思うのですが。

スキルアップ/キャリアアップ(JOB@IT)