Files
rikako-note/mysql/mysql文档/锁.md
2024-11-11 00:12:45 +08:00

3.5 KiB
Raw Blame History

lock 和 latch

在mysql数据库中lock和latch都可以被称之为锁但是两者锁包含意义不同。

latch

latch一般为轻量级的锁要求锁定时间通常非常短否则会影响性能。在innodb中latch可以分为mutex和rwlock。

latch通常被用于防止代码中临界资源的并发访问保证并发操作的安全性。latch操作通常没有死锁检测机制。

lock

lock和latch则稍有区别lock一般针对的是事务用于锁定数据库中的表、页、行等数据。并且lock一般在数据库事务进行commit或rollback后才释放

在innodb中lock拥有死锁检测机制。

latch和lock的比较如下

lock latch
对象 事务 线程
保护 数据库内容 代码中的临界资源
持续时间 整个事务过程 临界资源
模式 行锁、表锁、意向锁 读写锁、互斥量
死锁 通过waits-for graph、timeout等机制检测死锁 无死锁检测机制

在innodb中可以通过show engine innodb status以及information_schema下的innodb_trx来查看锁的情况。

innodb中的锁

innodb中针对行级锁有如下两种实现

  • S lock(共享锁):允许事务针对一行数据进行读取
  • X lock(排他锁):允许事务针对一行数据进行更新和删除

S lock和S lock之间可以互相兼容但是S lock和X lock、 X lock和 X lock之间都是不兼容的。当一个事务t持有某行数据的X lock时其他事务必须等待事务t提交或回滚之后才能获取该行数据的S lock或X lock。

除了行锁之外innodb还支持多粒度的锁定允许行级和表级的锁同时存在。为了支持该操作innodb引入了一种额外的加锁方式意向锁

意向锁

意向锁支持多粒度加锁,允许行锁和表锁共存。例如,lock tables ... write会在指定表上加X锁。为了在多个粒度上进行加锁innodb使用了意向锁意向锁是表级锁代表事务稍后需要为表中的数据加上哪种锁。

意向锁分为两种类型:

  • IS: 事务旨在为table中独立的行添加共享锁
  • IX: 事务旨在为table中的行添加排他锁

例如,select ... for share设置IS锁select ... for update则设置了IX锁。

意向锁协议如下:

  • 在事务获取table中某行记录的s锁之前其必须获取table的IS或更高级别锁
  • 在事务获取table中某行记录的x锁之前其必须获取table的IX锁

table level锁的兼容性如下所示

x ix s is
x 不兼容 不兼容 不兼容 不兼容
ix 不兼容 兼容 不兼容 兼容
s 不兼容 不兼容 兼容 兼容
is 不兼容 兼容 兼容 兼容

如果要加的锁和已经存在的锁兼容,那么它将被授予请求加锁的事务;要加的锁和已经存在的锁冲突时,则不会授予。请求加锁的事务将会阻塞,一直等待到存在冲突的锁被释放。

如果事务中的锁请求因为与现有锁冲突而无法被授予,并且造成死锁,那么会抛出异常。

意向锁和意向锁之间是兼容的,故而意向锁只会和全表扫描相冲突。

引入意向锁的意图是展示有人锁定了表中的某一行,或是将要锁定表中的某一行。

事务和意向锁相关的信息可以通过show engine innodb status来展示,其输出如下:

TABLE LOCK table `test`.`t` trx id 10080 lock mode IX