mysql-refman-5.7, 14.7.2.1 事务隔离级别,说:
在 READ COMMITTED 下,
- “对于 UPDATE 或 DELETE 语句,InnoDB 仅对其更新或删除的行持有锁。在 MySQL 评估 WHERE 条件后释放不匹配行的记录锁。”
- “但是,如果 WHERE 条件包含索引列,并且 InnoDB 使用索引,则在获取和保留记录锁时只考虑索引列。”
那么,第一个描述与第二个描述冲突吗?
这是示例:
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 的记录呢?