- - PR -
Insertが先 Updateが先
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-07-24 08:57
SQL Serverという前提で、私もWITH(UPDLOCK)がいいと思います。
SELECT ... FROM ... WITH (UPDLOCK) WHERE ... という感じです。 3番ということになりますね。 | ||||||||||||
|
投稿日時: 2008-07-24 10:17
PostgreSQL 8.0でトランザクションのSAVEPOINTがサポートされました。 INSERT前にSAVEPOINTを実行しておけば、INSERT失敗後にROLLBACK TOで戻って、UPDATEを再試行することが可能です。 #つーか、PostgreSQLのこの仕様だけは許せない。 | ||||||||||||
|
投稿日時: 2008-07-24 11:16
盛り上がってますね。
このケースで、select for update や UPDLOCK はどのような効果があるのでしょうか?対象行が存在すれば行をロックすることができますが、対象行が存在しなければロックをおこなうことができませんよね。結果として「UPDATE できないから INSERT を試みる」というプロセスが同時に複数発生することを抑制できないように思います。 このケースでは、select for update や UPDLOCK は意味を持たず、直接 UPDATE ステートメントを実行するのと同じではありませんか?この方法で、他プロセスとの排他制御を適切におこなえるとは思えません。 データベースだけで確実に排他制御をおこなうには、テーブルロックするしかないように思えます。他には、「これらの INSERT/UPDATE 操作をおこなうには、事前に○○を排他的に取得していなければならない」というルールを作りアプリケーションレベルで排他制御をおこなうことも考えられますが、ルールを守らないアプリケーションが直接 UPDATE/INSERT 操作をおこなう可能性を排除できません。私は、パフォーマンスを考慮して、テーブルロックではなくアプリケーションレベルで排他制御をおこなうことが多いです。 | ||||||||||||
|
投稿日時: 2008-07-24 12:42
おお。その手がありますね。気づきませんでした。 私は基本的にJava屋なので.NETでどうなのか知りませんが、 トランザクションコーディネータを利用した場合はどうなのでしょうか?
その通りだと思います。
そうですね。確実に行う方法はテーブルロックだけでしょう。 ただ、アプリケーションでの排他制御は負荷分散した場合に 問題が起きるので避けた方がいいと思います。 | ||||||||||||
|
投稿日時: 2008-07-24 14:23
そっか、登録順の制御しないならそれでもいいですね。 逆に登録順の制御が必要なら、もっと別のところで制御しなくちゃならないし。 | ||||||||||||
|
投稿日時: 2008-07-24 14:52
つまりファントムが問題なわけで、トランザクション分離レベルをSerializableにすれば解決できるかな? もっとも、ほとんどのRDBMSでは同時実行性が大幅に低下すると思いますが。 | ||||||||||||
|
投稿日時: 2008-07-24 18:20
ファントムではないと思います。 見えていたはずのデータが見えないわけではないですし。 OracleやPostgreSQLのようなスナップショット型の分離レベルを 採用しているDBMSではSERIALIZABLEではこの問題は解決できません。 このような状況だけに限りませんが、再試行が必要になります。 #というか、前に見た時より新くなっていることを検出して #トランザクションの結果をロールバックのみに設定するだけ。 SERIALIZABLEが伝統的なインデックスなどの読み取りロックで実現されて いるならば、最初にSELECTをすることでINSERTは競合しなくなりますが、 排他ロックへのアップグレードでデッドロックの発生率が上がるはずです。 というわけで、やはりこちらも再試行が必須になります。 | ||||||||||||
|
投稿日時: 2008-07-24 20:02
こんばんは、のん吉です。
思いのほか盛り上がっていてビックリです。。。 やはり、B番でロックかけてですね。 @とAの話は、処理によって後書き優先でいい場合は可能? (PostgreSQLは使った事が無かったのですがクセありますね。) 皆さん、前提が少ないなかで ご意見頂き、有難う御座いました。 遅ればせながら、DBは SQLServer2005を採用しています。 |