[精选]详细介绍MySQL中常见的锁
大家好,又见面了,我是全栈君。
一、死锁示例
考虑下面一个 MySQL 死锁的示例:
有如下一张表:
CREATE TABLE `test` (
`id` int(20) NOT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
表中有如下数据:
mysql> SELECT * FROM test;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
| 5 | 5 |
| 10 | 10 |
| 15 | 15 |
| 20 | 20 |
| 25 | 25 |
+----+------+
6 rows in set (0.00 sec)
当 数据库 的隔离级别为Repeatable Read或Serializable时,我们来看这样的两个并发事务(场景一):
上面两个并发事务一定会发生死锁(这里之所以限定 RR和Serializable 两个隔离级别,是因为只有这两个级别下才会有 间隙锁/临键锁 ,而这是导致死锁的根本原因,后面会详细分析)。
我们再来看另外一个并发场景(场景二):
在这个并发场景下,两个事务均能成功提交,而不会有死锁。
在上面的示例中, 我们发现,select … for update虽然可以用于解决数据库的并发操作,但在实际项目中却不建议使用,原因是当查询条件对应的记录不存在时,很容易造成死锁。而造成死锁的原因和MySQL的锁机制有关。 本文将详细介绍常见的七种锁机制,了解了这些锁机制之后就能理解造成场景一死锁的根本原因以及场景一和场景二差异的原因。
二、MySQL的七种锁
- 行锁(Record Locks)
- 间隙锁(Gap Locks)
- 临键锁(Next-key Locks)
- 共享锁/排他锁(Shared and Exclusive Locks)