我正在阅读有关 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 中的第二个命令是 insert
,行为也是相同的。谁能描述一下这个例子背后的锁定背景(锁定的位置和原因)?
最佳答案
InnoDB 设置特定类型的锁如下。
SELECT ... FROM 是一致读取,读取数据库的快照并且不设置锁定,除非事务隔离级别设置为 SERIALIZABLE。对于 SERIALIZABLE 级别,搜索会在遇到的索引记录上设置共享的下一键锁。
SELECT ... FROM ... LOCK IN SHARE MODE 在搜索遇到的所有索引记录上设置共享的下一键锁。
对于搜索遇到的索引记录,SELECT ... FROM ... FOR UPDATE 阻止其他 session 执行 SELECT ... FROM ... LOCK IN SHARE MODE 或读取某些事务隔离级别。一致读取将忽略读取 View 中存在的记录上设置的任何锁。
UPDATE ... WHERE ... 为搜索遇到的每条记录设置排他的下一键锁。
DELETE FROM ... WHERE ... 为搜索遇到的每条记录设置排他的下一键锁。
INSERT 在插入的行上设置排他锁。这个锁是index-record lock,不是next-key lock(即没有gap lock),不会阻止其他session插入插入行之前的gap。
InnoDB 有几种类型的记录级锁:
记录锁:这是对索引记录的锁。
间隙锁:这是对索引记录之间的间隙进行锁定,或者对第一条索引记录之前或最后一条索引记录之后的间隙进行锁定。
Next-key lock:这是索引记录上的记录锁和索引记录之前的间隙上的间隙锁的组合。
查看更多:
关于mysql - innodb 隔离级别和锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9354022/