- - PR -
Insertが先 Updateが先
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-07-23 20:43
こんばんは
MySQLの場合 2番は変更のない更新の場合0件になってしまうので論外ですね。 | ||||||||||||
|
投稿日時: 2008-07-23 21:06
3 の場合、Select の結果「既存レコードがない」と分かったとして、Insert するまでの間に別のセッションから Insert されたらどーしましょ? 自セッションの Insert は失敗しますよね? そしたらもっかい Select して Update みたいにリカバリします? それとも Select する前にロックします? それもまた、システムのパフォーマンスに悪影響を与える可能性が高いやも。 なんてのもあって
てことになると思います。 [ メッセージ編集済み 編集者: 渋木宏明(ひどり) 編集日時 2008-07-23 21:20 ] | ||||||||||||
|
投稿日時: 2008-07-23 23:13
この手法はPostgreSQLだと問題が起きます。 エラーが発生したトランザクションはロールバックしか出来ないので。 それ以外のDBの場合は、この選択肢の中で確実に更新出来るのはこれだけです。
複数のトランザクション間でINSERTが競合する可能性があります。
これも複数のトランザクション間でINSERTが競合する可能性があります。 こういった更新を(PostgreSQLでも問題なく)確実に行うには、 1. 親レコードもしくはテーブルを排他ロックして更新を行う 2. SELECTした結果に応じてINSERT/UPDATEを使い分ける ⇒ 主キー制約違反が起きたらトランザクションを再試行 3. MERGEなどのINSERT/UPDATEの複合構文を使う のどれかになると思います。 私は、親レコードのロックが利用可能な場合は1を使い、 そうでない場合は2を使うことが多いです。 | ||||||||||||
|
投稿日時: 2008-07-23 23:54
発生条件がわからなかったので「環境によっては」なんて曖昧な表現を使ってしまったのですが、PostgreSQL特有の事象だったんですね。 1年前から持っていた疑問が解けました。ありがとうございます。 | ||||||||||||
|
投稿日時: 2008-07-24 00:10
select for update使いますね。
で、レコードがあれば、更新、なければ挿入です。 そして、挿入時にナチュラルキー等で一意制約違反になった場合、 素直にエラー扱いにすることが多いです。 | ||||||||||||
|
投稿日時: 2008-07-24 00:25
このテーブルのレコードがDeleteされることはあるんでしょうか、それにもよりますよねきっと。 「私はいつもこうやる」というわけではないですが、出てない方法として、 Insert Select not exists(〜)して件数が0件だったらUpadateする。これなら、 件数チェックで0件だったらから、Insertしたつもりが他でInsertされてた、 みたいな事が起きません。 ただ、速さを気にしないなら1番もありだし、終始ロックすれば2番もありだし、です。 MySqlだとREPLACE文というのがありますね。 というわけでJittaさんの意見に一番近いです。 [追記]ん、私の方法はrainさんの最初のレスの方法と原理的には一緒か。 [ メッセージ編集済み 編集者: べる 編集日時 2008-07-24 00:29 ] | ||||||||||||
|
投稿日時: 2008-07-24 00:44
こんばんわ、もう回答いらないかもしれませんが
私も3番ですね。 かつのりさんと一緒で、基本はSELECT FOR UPDATEを使います。 場合によってはNOWAITも一緒に指定して処理を待たずに エラーを意図的に返したりもします〜。 | ||||||||||||
|
投稿日時: 2008-07-24 08:02
さかもとです。
この場合は例外として処理します。 小規模システムで、同時実行が運用でカバーされているケースではCount→Insert or Updateの判断で済ますことが多いですが、認識不足でしょうか・・・? もちろんビジネスロジックでトランザクションの。。。という設計は必要ですが本件とは少し外れますので省略します。
要件によっては(SQL Serverの場合ですが) WITH(XXXLOCK) ですね。 パフォーマンスへの影響などは別途検討しますが、業務的な排他制御が必要なケースではスキーマの変更も含め厳格にロックします。 何にせよ、要件次第という条件はつきますが。 DBMSの特性によって違うとは知りませんでした・・・勉強になります。 _________________ ------------------------------------------ 拝啓、さかもとと申します♪ |