MySQL 锁

数据库锁的分类

按照锁的粒度划分:

  • 表级锁
  • 行级锁
  • 页级锁

按照锁的级别划分:

  • 共享锁
  • 排它锁

按照使用方式划分:

  • 乐观锁
  • 悲观锁

行级锁、表级锁、页级锁

1. 行级锁

行级锁是 MySQL 中锁定粒度最细的一种锁,表示只针对当前行进行加锁。行级锁分为共享锁和排他锁。

特点:

  • 开销大,加锁慢
  • 会出现死锁
  • 锁定粒度最小,发生锁冲突的概率最低,并发度最高

2. 表级锁

表级锁时 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表进行加锁。最常用的 MyISAM 和 InnoDB 都支持表级锁。

特点:

  • 开销小,加锁快
  • 不会出现死锁
  • 锁定粒度最大,发生锁冲突的概率最高,并发度最低

3. 页级锁

页级锁是 MySQL 中锁定粒度介于表级锁和行级锁之间的一种锁。

特点:

  • 开销和加锁时间介于表级锁和行级锁之间
  • 会出现死锁
  • 锁定粒度介于表锁和行锁之间,并发度一般

1a851e90-0d5c-4d4f-ac54-34c20ecfb903

共享锁和排他锁

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
2
SELECT ... LOCK In SHARE MODE;
SELECT ... FOR UPDATE;