mysql-refman-5.7、14.7.2.1 トランザクション分離レベル、次のように述べています。
READ COMMITTED の下で、
- 「UPDATE または DELETE ステートメントの場合、InnoDB は更新または削除する行に対してのみロックを保持します。一致しない行のレコード ロックは、MySQL が WHERE 条件を評価した後に解放されます。」
- ただし、WHERE 条件にインデックス付きの列が含まれ、InnoDB がインデックスを使用する場合、レコード ロックを取得および保持するときに、インデックス付きの列のみが考慮されます。
では、1 番目の説明は 2 番目の説明と矛盾しますか?
次に例を示します。
mysql> show create table t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
KEY `b` (`b`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> select * from t order by b,c;
+---+------+------+
| a | b | c |
+---+------+------+
| 2 | 2 | 4 |
| 1 | 3 | 3 |
| 3 | 3 | 4 |
| 4 | 5 | 6 |
+---+------+------+
# Session A:
mysql> set TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update t set c = 5 where b=3 and c =3;
Query OK, 1 row affected (0.00 sec)
Session B:
mysql> set TRANSACTION ISOLATION LEVEL READ COMMITTED;
mysql> update t set c = 2 where b=3 and c =4; # waiting for lock
では、セッション A は b=3 のすべてのレコードをロックしますが、b=3 と c=3 のレコードだけをロックしないのはなぜでしょうか?