- PR -

oracle レコードロックについて

投稿者投稿内容
ビギ
ベテラン
会議室デビュー日: 2006/04/03
投稿数: 56
投稿日時: 2008-05-27 21:49
ほったてさん、ありがとうございます。
実際のデータは、1件目のデータはupdateで成功していて、
2件目が本来はupdateなのに、insertしてしまっているのでエラーになっています。
エラーの時は、rollbackしていて、実際のデータは1件も更新されていないので
自動コミットは有効になっていないと思います。

BETWEENでもfor update 使えるんですよね???
ina
ベテラン
会議室デビュー日: 2005/04/14
投稿数: 58
投稿日時: 2008-05-27 22:07
「フェッチ・アクロス・コミット」を行っているため、上手く更新できないのでは?
また、select for update は、あくまでも「セレクトした行をロック」のはずだから、「insertしようとしたら別トランザクションから既にinnsertされてた」ってことがあるのでは?
※merge文にして「update xx set a = a+1」とかなら大丈夫?
ビギ
ベテラン
会議室デビュー日: 2006/04/03
投稿数: 56
投稿日時: 2008-05-27 22:42
inaさん、ありがとうございます。
「フェッチ・アクロス・コミット」というのもあるんですね。
確かに、selectのループ内でinsert、updateをしています。
commitはしていないんですが。^^;

更にご指摘の通り、
別トランザクションから既にinsertされてる可能性はありますよね。
MERGEだとinsertもupdateも一文で、できそうですし、これだと
他から更新される可能性はないのでしょうか?
ただ、なかなか難しくて、MERGEのSQL文がなかなかうまくできません。
必要としている内容に似たような例文を見つけたのに。。。(悲)

いっそ やはり「LOCK TABLE」でしょうか。
LOCK TABLEってあまり使わないものなのでしょうか?

ビギ
ベテラン
会議室デビュー日: 2006/04/03
投稿数: 56
投稿日時: 2008-05-27 23:24
MERGE文、できました!
SQL*plus worksheet で試したら
うまく insertとupdateをしてくれました。
便利ですね、MERGEって。。。
あとは明日、これをCGiアプリに組み込んで試して見ます。
この文があれば、「LOCK TBALE」も怖くない気がします。

うまくいったら またご報告させていただきます。
ina
ベテラン
会議室デビュー日: 2005/04/14
投稿数: 58
投稿日時: 2008-05-27 23:50
ところで、使用言語は何ですか?
できるだけスリムなコードにし、かつ、エラー発生箇所およびエラーメッセージまでを記載しておくと、有識者の方もご教示しやすくなると思いますので、記載してみてはいかがでしょうか?

また、冷静に考えるとinsert時はmergeでも「排他」にはなりそうも無いので、以下の様な仕組みにでもしたらどうでしょうか?


1)このテーブルの排他処理を管理するテーブルを作成 (カラムはseq(key),from,end)
2)上記テーブルに、今回処理する範囲のデータが登録されていないかチェック
  → 登録されていたら、sleepして登録されていない状態になるまで待つ など
3)(別トランザクションで)上記テーブルに今回登録する範囲のデータを追加してコミット
   例)seq=1, from=2008/06/01 00:00, end=2008/06/01 00:10
4)処理を実行
5)(別トランザクションで)上記2)で登録したデータを削除してコミット

※余り深く考えていないので、考慮の余地は多分にあると思いますが...
ビギ
ベテラン
会議室デビュー日: 2006/04/03
投稿数: 56
投稿日時: 2008-05-29 16:00
使用言語はc++で、cgiアプリケーションを作成しています。

登録するすべての「日時分、数」をテンポラリーテーブルに作成し、
MERGEの1文で対応できました。

まだまだ他の作りこみが多いので、
とりあえず先に進めるために「lock table」を使ってしまいましたが、
最終的には、inaさんのアドバイスのように登録する範囲の管理テーブルを組み込みたいと思います。

みなさん、いろいろとありがとうございました。
また別件で書き込みするかもしれませんが、よろしくお願いします。

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