2016-10-18 6 views
2

私は、一意性保証が必要なテキスト列を持つテーブルを持っています。テキスト列に一意の制約を付けることはできないので、一意性保証を保証するためにトランザクションを使用して挿入を囲みたいと思っています。一意のテキストを挿入するために最低限必要な分離レベルは?

私の質問です:この保証には最低限の分離レベルが必要ですか?

+1

この質問を重複して閉じるよう投票しました。とにかく、トランザクションの振る舞いは一意性を強制しないので、あなたは間違った戦略をとにかく追求していました。 –

+2

@BillKarwin私はこの質問が重複しているとは思っていません。他の質問への回答は、代替解決策を提供しますが、それは許されるはずです。 OPに答えるために、 'SERIALIZABLE'はあなたが行くことができる最高ですが、*すべての状況での一意性を保証するにはまだ十分ではありません。 http://kejser.org/race-condition-when-creating-unique-values/ – bishop

+0

@BillKarwinこれはあなたが投稿したものと重複していません。この質問は、テキストをユニークにするために必要な分離レベルについて質問しています。もう1つは、テキスト列にユニーク制約を作成するかどうかを尋ねます。 – Glide

答えて

2

一意性を保証するトランザクションの使用はありません。

これには、UNIQUE制約を使用してください。

しかし、768バイトを超える一意のインデックスを含むインデックスは作成できません。どの

あなたはユニークな長い文字列の先頭部分を作るためにプリフィックス索引を使用することができるなど、あなたが特定の長さにわたってTEXTVARCHARのように長い文字列のデータ型にユニーク制約を置くことができないことを意味します。

ALTER TABLE MyTable ADD UNIQUE KEY (textfield(255)); 

一意性を確保する別の方法は、挿入したい値のための既存の行を検索し、それが見つからない場合にのみ、新しい値を挿入することです。

しかし、同じ値を挿入しようとする別の同時セッションの競合状態を避けるためには、テーブルへの排他的アクセス権が必要です。

これは、トランザクション分離レベルとはまったく関係ありません。 SERIALIZABLEの分離レベルでさえ、競合状態を回避するのには役立ちません。言うこれhttp://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.htmlを読む:[SERIALIZABLE]

REPEATABLE READ似ていますが、自動コミットが無効になっている場合InnoDBは暗黙のうちにSELECT ... LOCK IN SHARE MODEにすべてのプレーンSELECT文に変換します。

したがって、重複した値をチェックするために複数のセッションが並行してテーブルを読み込もうとすると、共有ロックは他の共有ロックをブロックしないため許可されます。次に、彼らはすべては、新しい値を挿入することは安全であると判断し、重複している可能性があります。

表の読み取り時に排他ロックを取得するには、SELECT ... FOR UPDATEを明示的に使用します。しかし、これはトランザクション分離レベルで行うことができます。

+0

「SELECT unique_text_column FOR UPDATE」は、一意のテキストが確実に存在するかどうかを教えてくれますか?もしそうであれば、 'INSERT unique_text into table'ステートメントを実行して、同じ一意のテキストを挿入している他のセッションがないようにする必要はありませんか? – Glide

+0

はい、SELECTとそれ以降のINSERTを1つのトランザクションで実行する必要があります。そうしないと、SELECT FOR UPDATEによって作成されたロックが解放されます。しかし、これは分離レベルとは関係ありません。 –

+0

しかし、隔離レベルは、他のセッションが見ているものを決定しませんか?すなわち、セッションAはトランスを開始し、「select unique_text_for update」、「INSERT unique_text into table」を開始する。セッションBはトランザクションを開始し、同じことを行います。 Bのトランザクション 'READ_UNCOMMMEDED'と' Serializable'の分離レベルを設定すると、異なる結果が得られますか?つまり、 'READ_UNCOMMITED'はAの挿入を見ません。 – Glide

関連する問題