9

innodb トランザクションに関するマニュアルを読んでいますが、まだ不明な点がたくさんあります。たとえば、次の動作はよくわかりません。

-- client 1                             -- client 2
mysql> create table simple (col int) 
       engine=innodb; 

mysql> insert into simple values(1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into simple values(2);
Query OK, 1 row affected (0.00 sec)

mysql> select @@tx_isolation;                                                              
+-----------------+                                                                         
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |                                                                         
+-----------------+

mysql> begin;                                    
Query OK, 0 rows affected (0.01 sec)            
                                        mysql> begin;
                                        Query OK, 0 rows affected (0.00 sec)

mysql> update simple set col=10 where col=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

                                         mysql> update simple set col=42 where col=2;
                                         -- blocks

ここで、最後の更新コマンド (クライアント 2 内) が待機します。行1のみがロックされていると思われるため、コマンドが実行されると予想されます。クライアント 2 の 2 番目のコマンドが であっても、動作は同じですinsert。この例の背後にあるロックの背景 (ロックの場所と理由) を説明できる人はいますか?

4

3 に答える 3

10

InnoDB は、特定のタイプのロックを次のように設定します。

  • SELECT ... FROM は整合読み取りであり、データベースのスナップショットを読み取り、トランザクション分離レベルが SERIALIZABLE に設定されていない限りロックを設定しません。SERIALIZABLE レベルの場合、検索は、検出したインデックス レコードに共有次キー ロックを設定します。

  • SELECT ... FROM ... LOCK IN SHARE MODE は、検索で検出されたすべてのインデックス レコードに共有次キー ロックを設定します。

  • 検索で検出されたインデックス レコードの場合、SELECT ... FROM ... FOR UPDATE は、他のセッションが SELECT ... FROM ... LOCK IN SHARE MODE を実行したり、特定のトランザクション分離レベルで読み取ったりするのをブロックします。一貫した読み取りは、読み取りビューに存在するレコードに設定されたロックを無視します。

  • UPDATE ... WHERE ... は、検索で検出されたすべてのレコードに排他的な次のキー ロックを設定します。

  • DELETE FROM ... WHERE ... は、検索で検出されたすべてのレコードに排他的な次のキー ロックを設定します。

  • INSERT は、挿入された行に排他ロックを設定します。このロックはインデックス レコード ロックであり、ネクスト キー ロックではなく (つまり、ギャップ ロックはありません)、他のセッションが挿入された行の前のギャップに挿入することを妨げません。

InnoDB には、いくつかのタイプのレコードレベル ロックがあります。

  • レコード ロック: これはインデックス レコードに対するロックです。

  • ギャップ ロック: これは、インデックス レコード間のギャップに対するロック、または最初のインデックス レコードの前または最後のインデックス レコードの後のギャップに対するロックです。

  • 次キー ロック: これは、インデックス レコードに対するレコード ロックと、インデックス レコードの前のギャップに対するギャップ ロックの組み合わせです。

続きを見る :

Next-Key Locking を使用してファントムの問題を回避する

デッドロックの回避

于 2012-02-24T05:30:40.480 に答える
1

ypercubeはそれを正しく持っています。具体的には、条件で使用される一意のインデックスがないと、影響を受ける単一の行よりも多くがロックされます。

期待する動作を確認するには、テーブルの作成を次のように変更します。

create table simple (col int unique) ENGINE=InnoDB;

フィールドの一意のインデックスによりcol、影響を受ける行のみをロックできます。

于 2012-02-23T17:34:29.707 に答える
0

「検索で検出されたインデックス レコードの場合、SELECT ... FROM ... FOR UPDATE は、他のセッションが SELECT ... FROM ... LOCK IN SHARE MODE を実行したり、特定のトランザクション分離レベルで読み取ったりすることをブロックします。一貫した読み取りは、ロックを無視します。読み取りビューに存在するレコードに設定されます"

他のセッションがロックされたレコードを読み取れないように select for update で適用できる特定のロックは何ですか?

于 2014-06-16T06:24:06.190 に答える