2016-08-26 2 views
2

InnoDBロックについてのmysqlリファレンスマニュアルを読んでいます。 INSERTは、挿入された行に排他ロックを設定コミットがデッドロックを引き起こさない理由


: ( http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.htmlから:)私はそれを得ました。このロックは、次のキーロックではなくインデックスレコードロックです(つまり、ギャップロックはありません)。挿入された行の前に他のセッションがギャップに挿入されることを防ぎません。

前に行を挿入し、ギャップロックのタイプは、インサート意図ギャップロックが設定されていると呼ばれます。このロックは、同じ索引ギャップに挿入された複数のトランザクションが、ギャップ内の同じ位置に挿入されていない場合、互いを待つ必要がないように、挿入の意図を通知します。 4と7の値を持つ索引レコードがあるとします.5と6の値を挿入しようとする個別のトランザクションは、挿入された行の排他ロックを取得する前に、挿入意図ロックで4と7の間のギャップをロックします。行が競合していないため、互いにブロックします。

重複キーエラーが発生した場合、重複したインデックスレコード上の共有ロックが設定されています。このような共有ロックを使用すると、別のセッションがすでに排他ロックを持っている場合に同じ行を挿入しようとするセッションが複数ある場合、デッドロックが発生する可能性があります。これは、別のセッションが行を削除した場合に発生する可能性があります。 InnoDBのテーブルT1には、以下の構造を有すると仮定する:

は、テーブルT1(iはINT、PRIMARY KEY(I))ENGINE = InnoDBテーブルを作成します。

セッション1: は今3つのセッションが順番に次の操作を実行したと

START TRANSACTION; 
INSERT INTO t1 VALUES(1); 

セッション2:

START TRANSACTION; 
INSERT INTO t1 VALUES(1); 

セッション3:

START TRANSACTION; 
INSERT INTO t1 VALUES(1); 

セッション1:

セッション1によって
ROLLBACK; 

最初の動作は、行に対する排他ロックを取得します。セッション2とセッション3による操作の結果、重複キーエラーが発生し、両方がその行の共有ロックを要求します。セッション1がロールバックされると、行に対する排他ロックが解除され、セッション2および3のキューに入れられた共有ロック要求が許可されます。この時点では、セッション2と3はデッドロックしています。他方は共用ロックを保持しているため、行の排他ロックを取得できません。


私は実験を行いましたが、それは事実です。

私の質問は:

(1)私はセッション1をコミットした場合、ことがわかった、とデッドロックが発生しませんでした。どうして?セッション1をコミットすると、X行ロックも解放されます。だから私は理解していない。

Thx。

答えて

0

これは、これが効率的にする価値のないエッジケースだと思われます。あなたは同じ行をつかむために3つのセッションを取らなければならなかったことに注意してください - まれな出来事です。そして、あなたはROLLBACKをやったこともあります。したがって、発生したデッドロックは過剰なものですが、修正する価値はありません。このため、どこにでもデッドロックを処理できるようにする必要があります。

FYI、これがGaleraクラスタの3つのノードの場合、コードが処理する必要があるエラーはCOMMITです。このトランザクションを複数のノードに複数回(ロールバックまたはコミットして)適用すると、さらに奇妙なことが起こることが考えられます。

あなたの質問に...おそらく、スレッドの1つが排他ロックを取得し、もう1つが「デッドロック」の代わりに「待機」でヒットしたため、デッドロックは発生しませんでした。

+0

おそらく、スレッドの1つが排他ロックを取得し、もう1つが「デッドロック」ではなく「待機」でヒットしたため、デッドロックは発生しませんでした.---セッション2とセッション3のいずれかが排他ロック?重複キーエラーが発生した後に共有ロックを要求していませんか? – XiaJun

+0

私はそれがその時点で物事を巻き戻す方法に精通していません。 –

関連する問題