MySQL 锁
数据库锁的分类
按照锁的粒度划分:
- 表级锁
- 行级锁
- 页级锁
按照锁的级别划分:
- 共享锁
- 排它锁
按照使用方式划分:
- 乐观锁
- 悲观锁
行级锁、表级锁、页级锁
1. 行级锁
行级锁是 MySQL 中锁定粒度最细的一种锁,表示只针对当前行进行加锁。行级锁分为共享锁和排他锁。
特点:
- 开销大,加锁慢
- 会出现死锁
- 锁定粒度最小,发生锁冲突的概率最低,并发度最高
2. 表级锁
表级锁时 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表进行加锁。最常用的 MyISAM 和 InnoDB 都支持表级锁。
特点:
- 开销小,加锁快
- 不会出现死锁
- 锁定粒度最大,发生锁冲突的概率最高,并发度最低
3. 页级锁
页级锁是 MySQL 中锁定粒度介于表级锁和行级锁之间的一种锁。
特点:
- 开销和加锁时间介于表级锁和行级锁之间
- 会出现死锁
- 锁定粒度介于表锁和行锁之间,并发度一般
共享锁和排他锁
1. 共享锁(S)
共享锁(Shared)又称读锁,是读取操作创建的锁。
如果事务 T 对数据 A 加上共享锁后,则其他事务只能对 A 再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
2. 排他锁(X)
排他锁(eXclusive)又称写锁。
如果事务 T 对数据 A 加上排他锁后,则其他事务不能再对 A 加上任何类型的锁。获取排他锁的事务既能读数据,又能修改数据。
共享锁和排他锁的兼容关系如下:
- | X | S |
---|---|---|
X | 冲突 | 冲突 |
S | 冲突 | 兼容 |
意向锁
意向锁是表级锁,但表示事务正在读写某一行记录,而不是整个表。所以意向锁之间不会发生冲突,真正的冲突发生在加行锁时检查。
1. 意向共享锁(IS)
表示事务准备给数据行加共享锁,也就是说事务在一个数据行加共享锁前必须先获取该表的 IS 锁。
2. 意向排他锁(IX)
表示事务准备给数据行加排他锁,也就是说事务在一个数据行加排他锁前必须先获取该表的 IX 锁。
悲观锁和乐观锁
1. 悲观锁
悲观锁机制认为每一步如果不采取同步措施都会出现问题,依赖于数据库的锁机制。关系型数据库里边就用到了很多悲观锁机制,比如行锁、表锁等,读锁、写锁等,都是在做操作之前先上锁。
如果锁定时间过长,用户长时间无法访问,会影响程序的并发访问。
2. 乐观锁
先执行,如果存在冲突,则采取一个补偿措施(比如告知用户失败)。一般有 2 种实现方式:
- 使用版本号
- 使用时间戳
MySQL 隐式与显式锁定
MySQL 的 InnoDB 存储引擎采用两段锁协议,会根据隔离级别在需要的时候自动加锁,并且所有的锁都是在同一时刻被释放,这被称为隐式锁定。
InnoDB 也可以使用特定的语句进行显示锁定:
1 | SELECT ... LOCK In SHARE MODE; |