21:09:39.15ID:KSci4OQ9�@と�AをSerializableなトランザクションでやればいい。20:31:32.61ID:dDBcLzC2できるだろ。14:33:26.91ID:SnTWW0f8>>476こういうケースで問題がある。integer)user1がa=3のレコードを、user2がa=4のレコードを同時に作成しようとする。本来なら、別のデータを登録する処理なので、両立すべき。commit;結果として、user2はデータを登録できない。22:22:51.33ID:/ybRo7IQ>>469の要件は満たしてるのに、>本来なら、別のデータを登録する処理なので、両立すべき。なんでこういう条件を勝手に追加するんだか。それぞれのトランザクション分離レベルで守らなければならないことと実装に任されていることとの区別もついていないようだ。found)、user1のブロック解除これをエラーにする必要もないんだが。なんでこういう条件を勝手に追加するんだか。別に勝手に追加したわけじゃなくて、>>477は普通の正常系の話。複数人が別々のデータを同時に登録するなら、それは成功してしかるべき。これをエラーにする必要もないんだが。なければinsert」という処理を普通に行う実装で、「->」以降はそれを実行した結果。要件は満たすしserializableの要件を満たすことが目的ではないし、普通に実装すればuser2はブロックしないし失敗もしない。これをエラーにする必要もないんだが。いう意味?エラーにするんじゃなくて、エラーが発生するんだけど。10:26:02.84ID:FG8f7euNというか、クライアントを二つ立ち上げて、>>477を実査にやってみれば、俺が言ってることを納得できると思う。22:41:53.12ID:d4TkCE35>別に勝手に追加したわけじゃなくて、>>477は普通の正常系の話。>複数人が別々のデータを同時に登録するなら、それは成功してしかるべき。そもそもトランザクションは常に失敗の可能性があるってことすら理解してないのか。>>469はそんなもの問題として挙げてないし、これが実際に問題となるかどうかはもう少し具体的にアクセス規模や性能要件なんかを出して議論するものだ。>serializableの要件を満たすことが目的ではないし、普通に実装すればuser2はブロックしないし>失敗もしない。>エラーにするんじゃなくて、エラーが発生するんだけど。>>478に書いた「実装」ってのはDBMSの実装のことな。SERIALIZABLEの要件を満たすのもエラーを出すのもDBMS側の仕事。データがないことを確認できる安直なDBMならここでtにテーブル排他ロックをかけるかもしれない。それを踏まえてもういちど>>478を読み返してみな。>というか、クライアントを二つ立ち上げて、>>477を実査にやってみれば、俺が言ってることを納得できると思う。>>478と同じことを書くけど、おまえさんはSQL標準で規定されたトランザクションの仕様と個々のDBMSの実装の区別がついていない。10:08:49.24ID:csb4seou>>481あ、MySQL前提じゃなかったんだね。20:31:43.28ID:goJly4rw返答ありがとうございました。前提条件が不明確でいらぬトラブルを生んでしまったかもしれません。明確に1レコードだけが挿入されるようにしたい」です。20:32:39.61ID:goJly4rw結局処理は、シリアライズな?トランザクションの使い方も良く分かっていないので以下のように設計しました。複数同時に走ったとしても一回しか通らないはずです。大丈夫ですよね?PDOを利用しています。よる挿入をブロックしなければならないのですが、オーソドックスなやり方を知りたいです。コードが正しいのか、タイミングをほぼ同時にできるかつ自動で微妙に時間をでずらすソフトを作成して、百本ノックならぬ100億本ノックで安全を担保しようとしています。凄くタコなやり方ですが、これ以外に安全を担保するやり方を知らないので。21:55:15.56ID:WV/fnjvUQテーブルに1レコードしか存在し得ないよう制約がかけられているのならOK。複数挿入できるならNG。そもそもそんなQテーブルが作れるのなら素直にZにユニーク制約をかけることを検討した方がいいんじゃないかとは思うが。あと、ロングトランザクションなら楽観的ロックも仕方ないが、ちゃんとトランザクションの使い方を学んだ方が後々苦労せずに済むと思うがねぇ。00:33:23.21ID:nGqVI4Wr>>4691で存在チェックしてから、2で挿入するって、1と2の間に、他のプロセスが割り込めるから、典型的なダメパターン。教科書に書いてある、やっちゃいけない事前問い合わせ一々、2回もSQL実行するのは無駄。10:25:48.93ID:lxKZC7pd>>485おい、いつのまにか対象とするテーブルが一つから二つに増えてるぞ。あと、値が49ってなんだよ・・・。大丈夫ですよね?全然駄目。すなおにテーブルロックすべし。10:39:25.56ID:13McY78U返答ありがとうございます。一つ間違っていました。レコードを〜」でした。>>486>Qテーブルに1レコードしか存在し得ないよう制約がかけられているのならOK。複数挿入できるならNG。複数挿入できないように制約をかけます。SELECT(行が無ければ挿入?)で実現しようとしています。>>487テーブルロックは使わない方法でご教授いただければと思います。必要ないのですが、念のために入れてるだけです。>>490テーブルロックは使わない方法でご教授いただければと思います。指摘を受けてハッとしました。やりたい事を伝え忘れていました。レコード」は結果テーブル1行だけというのは変わらないのですが、その直前にわりと大きめのトランザクションが走ります。そのトランザクションが複数走るのではと心配になっていました。トランザクションはまとめて一気に走らせて「何かに失敗したら全部ロールバックできる便利な機能」位しか理解できていません。仕組みが良く分かっていないので今勉強中です。2人から同じご指摘いただいているので、普通はテーブルロックで行うって事ですよね。そちらも勉強して理解を深めようと思います。進捗があったらまた書き込ませていただきます。11:22:48.43ID:GozEyCoO>>492なんか話が変わってきているが、>>469に沿って言えば、Z.Xにユニーク制約を付けるのが「普通」。あと、トランザクションの大小は関係ない。3msで終了する「存在チェック→insert」というトランザクションでも、複数人が実行するのなら競合する可能性はある。22:39:01.72ID:JARk4f24>>492トランザクションを勉強するのはいいが、ロックのことは一旦忘れた方がいい。明示的にロックを「使う」なんて言うのはトランザクション分離レベルを理解できなかったジジイのやること。20:21:03.85ID:EI9/AJWb今回のケースに限らず、基本的にロックなんて使う必要ない。そもそも標準SQLにロックなんてないしな。必要があるとすれば、SQL92のトランザクション対応してない古いシステムでどうしてもやらないとならない場合とか、全部わかってる人があえて標準じゃできない使い方をする場合くらい。07:48:18.17ID:4rtM9TBt>理想は分離レベルの指定だけで済ますことなんだが>現実的には、どの分離レベルでどういうSQL流したらどういうロックが獲得されるかはちゃんと理解しとかないとそれは別に相反する話じゃないが。今回の例ならSERIALIZABLEでトランザクション流せば良いだけ同じテーブルに同時に別のデータをINSERTすることがないという限定条件付きだけどな。普通は、同じテーブルに同時に別のデータをINSERTすることもあるし、同時に同じデータをINSERTすることもある。同時に同じデータをINSERTされないようにするには、普通はunique制限を付ける。なんらかの理由でunique制限を付けられない場合は、論理的にはテーブルをロックするしかない。その「テーブルをロックする」というのが、MySQLで上の限定条件に限り、目的と合致するというだけの話。10:18:08.32ID:99igoHFu>>500まず、俺がトランザクションについて理解していないとか、分離レベルについて理解していないとか、そういう思い込みを捨てろ。俺に言わせれば、お前の方が理解していないように見えるんだが。MySQLどうこうじゃなくて、SERIALIZABLEを正しく実装してる全てのDBMSで正しく動作するけど?いや、serializableなトランザクションに関する各RDBMSの実装が異なっているというのが前提で、だからこそ「serializableなトランザクションを使えばうまくいく」という一般論にはならない。「MySQLならこういう限定条件であればserializableなトランザクションを使えば良い」というようにしか言えない。user2が(ロックタイムアウトじゃなくて)デッドロックで落ちたりするのか?いやいや、実行結果って書いたじゃん。10:40:31.01ID:99igoHFuPostgreSQLでもやってみた。10:42:56.92ID:99igoHFu各RDBMSがserializableなトランザクションの実装で保証するのは「ファントムリードがないこと」であって、それを実現する方法は各RDBMSの実装にまかされている。serializable;は削除し忘れ。11:58:09.82ID:99igoHFu少し解説を加えると、RDBMSはserializableなトランザクション内の文脈を見て成功・失敗を決めているわけではなく、ただ単にファントムリードが発生しないような実装にしているだけ。あと、ロックと処理がブロックするというのは別の話。lockでも処理をブロックするという実装もありえる。serializableなトランザクションの場合、リトライすればOKな場合がある。そもそも、トランザクションが重ならなければお互いOKになる場合ね。CODEの内容からリトライ可能かどうかを判定してリトライするという実装が必要。1回だけのリトライではまた他のトランザクションと重なる場合があるので、MAX回数を決めてリトライを続ける必要がある。いう面倒くさいことをしてまでも、ファントムリードを防がなければならないケースに限って、トランザクションをserializableにするというのが正しい使いだと思う。ユニーク性を担保したいだけだったら、テーブルロックで十分。15:44:40.75ID:99igoHFu>>509デッドロックになるようなロックのかけ方すればエラーになるだろうけど、それと今回の話とは関係ないよね。22:23:54.80ID:fjXPLH9h>いや、serializableなトランザクションに関する各RDBMSの実装が異なっているというのが前提で、>だからこそ「serializableなトランザクションを使えばうまくいく」という一般論にはならない。この時点で理解してないのは明らか。そもそもSERIALIZABLEは無条件に直列化可能であることを保証するものだし。>各RDBMSがserializableなトランザクションの実装で保証するのは「ファントムリードがないこと」であって、>それを実現する方法は各RDBMSの実装にまかされている。ファントムリードが起きない「だけ」なんだが、直列化可能性を保証するにはそれで十分なわけ。「ファントムリードがない」ってのを、単に他トランザクションで挿入したレコードを見せないだけとでも思ってるんだろうか。10:04:35.37ID:uHWEQ8CC>>511もうお前の主張にはなにも興味はないが、mysqlとpostgresqlの実装にたいする感想くらいくれよ。serializableで単独テーブルに対するアクセスでデッドロックするのもどうなんだという感じがしないでもないがあ、これがmysqlの実装に対する感想なのか?じゃ、もういいや。10:14:11.58ID:uHWEQ8CC最後に一つだけ。「SERIALIZABLEは無条件に直列化可能であることを保証するもの」の意味が全然わからんが、ユニーク性を担保するためには、同時に実行される可能性があるトランザクションを「直列化」する必要があり、それにはテーブルロックを使うのが最も簡単。これに反論がある場合に限ってレスしてくれ。11:18:11.85ID:uHWEQ8CC>>515への直接のレスがなければ、これでserializable話は終了します。いい加減うざいだろうし。「serializableなトランザクションとは何か」は、以下のスライドが俺が見つけた範囲だと一番わかりやすいと思う(それでもわかりづらいんだが)。21:47:43.84ID:8O2pDGJY「SERIALIZABLEじゃ無理」→「問題がある」→「ロックの方が簡単」なんだかなぁw普通はトランザクション開始時に隔離レベルを1行指定する方がいちいちテーブルを指定してロックをかけるより簡単だと思うんだが。serializableにするというのが正しい使いだと思う。22:37:42.39ID:ZdJwFyPe今どきRDBMSとかダサすぎ。ようにbを入れるだけでここでスレ保存、閲覧できます。