天天看点

MySQL 与InnoDB 下的锁做朋友 (三)意向锁

前言  

该篇谈谈 意向锁。

正文

InnoDB supports multiple granularity locking which permits coexistence of row locks and table locks.

For example, a statement such as LOCK TABLES ... WRITE takes an exclusive lock (an X lock) on the specified table.

To make locking at multiple granularity levels practical, InnoDB uses intention locks.

Intention locks are table-level locks that indicate which type of lock (shared or exclusive) a transaction requires later for a row in a table. 

翻译:

InnoDB支持多粒度锁,允许行锁和表锁共存。

例如,LOCK TABLES之类的语句。。。WRITE在指定的表上采用独占锁(X锁)。

为了实现多粒度级别的锁定,InnoDB使用了意向锁。

意向锁是表级锁,用于指示事务稍后对表中的行需要哪种类型的锁(共享或独占)。

看这些文字,感觉就是比较模糊, 那么我认为我应该写一点小白文,能让大家稍微理解一下。

1.意向锁是表级锁。

   但是 这个意向锁是个特殊的表级锁,由存储引擎去维护, 它不跟行锁冲突,意向锁直接也不冲突因为引擎级别的特殊表级概念。

2.我们要清楚  正常的表锁和行锁是冲突的。

所以举个例子:

那么如果一个事务 A 对  用户表内数据 进行了 行锁排他锁操作;

事务B去获取这个用户表的写锁 排他锁时,第一步回去检测这个用户表是否上了表锁,如果没有,就会去检测这个用户表内数据有行锁锁定操作,导致 表&行锁冲突(如果存在冲突,就会进入等待行锁释放)。

问题就是在这, innodb 有行锁,有表锁,都支持。

如果说按照上面的例子,用户表 确实没有上 表锁锁定, 但是上了行锁锁定。

所以事务B为了检测里面是否真的有行锁锁定, 会对用户表做 行遍历,去找每一行是不是都没锁定操作,这样才能 获取表级写锁。

这样看上去效率就很低。

所以设计者 搞出了意向锁。

当一个事务A 准备对 用户表进行 行级锁定操作,InooDB 会先获取该数据行所在的表的对应意向锁,进行意向锁锁定操作。

这样事务B过来尝试对 用户表做表锁锁定操作时,申请锁资源时,只需要看下 用户表是否存在 意向锁锁定 ,如果有,直接去等待资源就行,这样就不需要遍历了(以免遍了N久才知道有冲突,还是需要等待)。

理解了这个意向锁的作用后,我们再来回归意向锁的一些介绍。

意向锁 分两种:

意向共享锁 (IS)

意向排他锁(IX)

我们对某个表 做行锁操作时, 行锁也分 S锁和 X锁 (上一篇我们有说到)。

所以,innodb引擎 在知道我们对某个表数据准备使用 S (共享读锁,我上篇有讲过的)行级锁定时,就会去对这些行 所在的表,做  意向共享锁 (IS) 锁定操作。

同样,innodb引擎 在知道我们对某个表数据准备使用X (排他写锁,我上篇有讲过的)行级锁定时,就会去对这些行 所在的表,做 意向排他锁(IX)锁定操作。

最后放出一个小表格,结束我们的意向锁简单介绍篇(看久了都快不认识兼字了):

(简单总结就是,意向锁互相不冲突。 意向锁和表级锁之间的冲突,满足我上一篇所说的 共享读锁和排他写锁之间的冲突规则)

标题 意向共享锁(IS) 意向排他锁(IX) 表级共享锁(S) 表级排他锁(X)
意向共享锁(IS) 兼容 兼容 兼容 不兼容
意向排他锁(IX) 兼容 兼容 不兼容 不兼容
表级共享锁(S) 兼容 不兼容 兼容 不兼容
表级排他锁(x) 不兼容 不兼容 不兼容 不兼容

ps:

小明:教练,我想 上意向锁!

继续阅读