- - PR -
oracle レコードロックについて
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2008-05-27 21:49
ほったてさん、ありがとうございます。
実際のデータは、1件目のデータはupdateで成功していて、 2件目が本来はupdateなのに、insertしてしまっているのでエラーになっています。 エラーの時は、rollbackしていて、実際のデータは1件も更新されていないので 自動コミットは有効になっていないと思います。 BETWEENでもfor update 使えるんですよね??? |
|
投稿日時: 2008-05-27 22:07
「フェッチ・アクロス・コミット」を行っているため、上手く更新できないのでは?
また、select for update は、あくまでも「セレクトした行をロック」のはずだから、「insertしようとしたら別トランザクションから既にinnsertされてた」ってことがあるのでは? ※merge文にして「update xx set a = a+1」とかなら大丈夫? |
|
投稿日時: 2008-05-27 22:42
inaさん、ありがとうございます。
「フェッチ・アクロス・コミット」というのもあるんですね。 確かに、selectのループ内でinsert、updateをしています。 commitはしていないんですが。^^; 更にご指摘の通り、 別トランザクションから既にinsertされてる可能性はありますよね。 MERGEだとinsertもupdateも一文で、できそうですし、これだと 他から更新される可能性はないのでしょうか? ただ、なかなか難しくて、MERGEのSQL文がなかなかうまくできません。 必要としている内容に似たような例文を見つけたのに。。。(悲) いっそ やはり「LOCK TABLE」でしょうか。 LOCK TABLEってあまり使わないものなのでしょうか? |
|
投稿日時: 2008-05-27 23:24
MERGE文、できました!
SQL*plus worksheet で試したら うまく insertとupdateをしてくれました。 便利ですね、MERGEって。。。 あとは明日、これをCGiアプリに組み込んで試して見ます。 この文があれば、「LOCK TBALE」も怖くない気がします。 うまくいったら またご報告させていただきます。 |
|
投稿日時: 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)で登録したデータを削除してコミット ※余り深く考えていないので、考慮の余地は多分にあると思いますが... |
|
投稿日時: 2008-05-29 16:00
使用言語はc++で、cgiアプリケーションを作成しています。
登録するすべての「日時分、数」をテンポラリーテーブルに作成し、 MERGEの1文で対応できました。 まだまだ他の作りこみが多いので、 とりあえず先に進めるために「lock table」を使ってしまいましたが、 最終的には、inaさんのアドバイスのように登録する範囲の管理テーブルを組み込みたいと思います。 みなさん、いろいろとありがとうございました。 また別件で書き込みするかもしれませんが、よろしくお願いします。 |