MySQL中InnoDB存储引擎之锁机制

  • 由于InnoDB存储引擎是MySQL的默认存储引擎,所以这里仅仅讲述的是InnoDB存储引擎的锁机制

一.InnoDB存储引擎中的锁

  • innodb存储引擎中实现了两种标准的行级锁(共享锁和排它锁),另外还支持一种名为意向锁的锁

1.1 两种标准的行级锁

  • 共享锁(S Lock):允许事务读取一行数据
  • 排它锁(X Lock):允许事务删除或更新一行数据

解释:

  • 如果一个事务需要获取T行的数据,仅仅是读取,那么就必须要先获取该行的共享锁。
  • 如果一个事务需要修改或者删除T行的数据,那么就必须先获取该行的排它锁。

锁特性:

  • 共享锁(S锁)允许多个读取数据的事务同时获得,也就是一个事务如果已经拥有了T行共享锁,那么另一个读取的事务也可以立即获取该行的共享锁。这种现象称之为锁兼容共享锁自身兼容。

  • 其实说明白一点就是允许多个事务一起读取该行,因为不修改数据。

  • 排它锁(X锁)自身不允许多个事务同时获取该行的X锁,并且如果该行的共享锁已经被其他事务获取了,那么其他事务无法同时获取其排它锁,必须等待获取该行共享锁的事务释放该行的共享锁,这种现象称之为锁不兼容。

  • 也就是不允许不同事务同时做读取和修改操作,也不允许不同事务同时做修改操作。排它锁自身不兼容,排它锁和共享锁也不兼容。

两种锁的兼容性如下:

X S
X 不兼容 不兼容
S 不兼容 兼容

总结:

  • 其实很容易理解,就是读取操作可以允许多个事务同时读取某一行的数据
  • 但凡涉及到修改删除的操作,就不允许多个事务进行访问该行。

1.2 意向锁

问题引入:多粒度锁定

  • 数据库中的数据存放是分级的,类似于 表——页——记录 这样的存储

  • 上述的两种锁都是行锁,也就是说每次事务都必须找到该行记录,才知道是否可以获取该行上的锁。也就是说每次都需要从数据库开始,到表,页等进行多次分级查找才可以找到,所以为了减少这样的查询,所以MySQL支持多粒度锁定

  • MySQL支持多粒度锁定,也就是说允许行级锁和表级锁同时存在。而为了支持这种多粒度锁定,引入了意向锁。

  • 举个例子,就是说我每次想查看我这个事务是否可以获取该行上的锁,就不需要查到行记录了,可能查到表级我就知道能不能获取到该行记录上的锁。

数据库层次结构:

MySQL技术内幕:InnoDB存储引擎之锁机制——详解

意向锁分类:

  • 意向共享锁(IS Lock):事务想要获取一张表中的某几行的共享锁
  • 意向排他锁(IX Lock):事务想要获得一张表中的某几行的排它锁

意向锁概述:

  • 意向锁是一种表锁,分为 IS 和 IX 两种意向锁

  • 意向锁是将锁定的对象分为多个层次,意味着事务希望在更细粒度上进行加锁。

  • 可以看到上述的数据库层次结构,我们将其看做一棵树。

  • 例如:

    1) 现在我们需要对记录R进行上X锁,那么就分别需要对数据库A,表,页上意向锁IX,最后对记录R上X锁。如果其中任何一个部分导致等待,那么该操作就需要等待粗粒度锁的完成。

    2) 如果我们对R加X锁之前,已经有事务对表1进行了S表锁,那么由于我对R加X锁之前还需要对表加 IX 锁,表锁出现了不兼容的情况,所以就需要等待表锁的完成。

注意:一个特别要注意的点

  • 这里有一个要非常注意的地方,Mysql是实现的行级锁,也就是说对同一个表中的不同行进行加X锁是不会被堵塞的。但是根据我们刚刚所讲述的意向锁,如果对某一个表中的不同行记录加 X 锁,在表级锁的判断兼容方面不就被堵塞了嘛?
  • 实际上由于InnoDB存储引擎支持的是行级别的锁,因此意向锁不会阻塞除全表扫描意外的任何请求。
  • 什么意思呢?其实意思就是IX 和 IS锁全部都是兼容的,他们不会出现上述的那种情况,一个表允许同时加IX和IS锁。

InnoDB存储引擎锁的兼容性如下:

MySQL技术内幕:InnoDB存储引擎之锁机制——详解

问题:

  • 这也是我的一个疑问?为什么S和X锁是行级锁,也可以加在表上?
  • 我个人的理解是对表加S锁是进行全局扫描的时候加的,这也是为什么意向锁只会阻塞全局扫描的操作!

相关文章: