本文主要介绍mysql的Innodb引擎下的各种锁。

S锁和X锁

mysql的Innodb存储引擎实现了两种行级别的锁:S锁(shared lock)和X锁(exculsive lock)

S锁

即可读取数据行所用的锁,即拥有该锁才可以去读取相应的数据行。

S锁与S锁是不会阻塞的,指的是同一条数据可以重复加S锁。

X锁

即可更新、删除数据行所用的锁,即拥有该锁才可以对相应的数据行进行更新删除操作。

X S
X 阻塞 阻塞
S 阻塞 非阻塞

在一个事务中,如果执行select,则就获取该条数据的S锁,如果执行update/delete,则就获取了该数据的X锁。

意向锁

为了支持多种粒度的锁机制,引入了意向共享锁(IS)和意向排他锁(IX)。它是一种表级别的锁,它不会阻塞任何操作(除了对表加锁的操作),它主要标识了有操作正在读表中的行数据或向表中写数据。

IS锁标识着有事务正在读取/准备读取行数据,IX锁标识着有事务正在/准备更新或删除行数据。

遵循以下规则:

  • 当我们读取表中的行数据时,首先要获取的表的IS锁,再获取该行数据的S锁。
  • 当我们要更新/删除表中的行数据时,首先要获取表的IX锁,再获取该行数据的X锁。
解决的问题
1
2
3
4
5
事务tx1:
update全表数据

事务tx2:
读取某一行数据

事务tx1和tx2一定是顺序执行,否则就会出现冲突。

如果不使用锁,那么只能通过设置串行化隔离级别,使事务串行执行,然而这样做性能最差。

还有种方式,每行数据更新时,需要判断该行数据是不是已被锁定。这样显然效率不高。

对于这种同时进行的更新操作,应先控制是否拥有该表的锁,通过表级别锁的控制,使事务操作串行。

mysql引入了意向锁,在事务开始时,判断能不能获取该表意向锁。对于上面的示例,tx1获取了表的IX锁,那么事务tx2开始时发现表已经被加了IX锁,那么就无法再加IS锁,事务tx2被阻塞。

X IX S IS
X 冲突 冲突 冲突 冲突
IX 冲突 兼容 冲突 兼容
S 冲突 冲突 兼容 兼容
IS 冲突 兼容 兼容 兼容

 评论