今天咱们来聊聊MySQL中InnoDB存储引擎的锁。算法
锁是数据库系统系统区别于文件系统的一个关键特性。数据库
latch
在MySQL中是用来保证并发多线程操做操做临界资源的锁
,锁定的对象线程,是和我们使用的Java等传统语言中的锁意义相近,并且没有死锁检测的机制。bash
lock
是MySQL中在事务中使用的锁
,锁定的对象是事务,来锁定数据库中表、页、行;一般只有在事务commit或者rollback后进行释放。lock是有死锁机制的,当出现死锁时,lock有死锁机制来解决死锁问题:超时时间(参数innodb_lock_wait_timeout
)、wait-for graph
。微信
咱们一般讲的MySQL的“锁”,通常就是说的lock。网络
如下就是InnoDB中“锁”的大分类:多线程
MySQL Lock大致上能够分为:表锁、行锁、意向锁三种。并发
行锁分为:S Lock
和X Lock
。S Lock
:读锁;X Lock
:写锁。 两锁之间的兼容性以下。ui
X S
X 不兼容 不兼容
S 不兼容 兼容
复制代码
简单总结为:读锁能够读,读锁不可写;写锁不可读也tm不可写。
spa
InnoDB支持多粒度的锁,即:容许表锁和行锁同时存在。 可是,假如表锁覆盖了行锁的数据,因此表锁和行锁也会产生冲突。如:线程
trx1 BEGI
trx1 给 T1 加X锁修改数据。
trx2 BEGIN
trx2 给 T1 加表锁修改表结构
复制代码
这样,表锁和行锁之间就产生了冲突,为了解决这种表锁和行锁共存的问题,就产生了意向锁
这个东西。 意向锁:从字面意思也很好理解,就是提早代表一个“意向”。
意向锁分为:
意向共享锁
。它预示着,事务有意向对表中的"某些行"加S锁。select xxxx lock in share mode
,要设置IS
锁。意向排他锁
。它预示着,事务有意向表中的“某些行”加X锁。select xxx for update
,要设置IX
锁。但意向锁仅仅是代表意向,它其实很是弱,意向锁之间能够相互并行,并非排斥的: 意向锁之间的兼容性问题:
IS IX
IS 兼容 兼容
IX 兼容 兼容
复制代码
可是,意向锁能够和行锁互斥。
S X
IS 兼容 互斥不兼容
IX 互斥不兼容 互斥不兼容
复制代码
因而,上述现象就变为了:
trx1 BEGIN
trx1 给 T1 先加IX ,而后在某一行记录加X锁。
trx2 BEGIN
trx2 给 T1 加表锁(事务被阻塞,等待加锁成功)
trx2 修改表结构
复制代码
自增锁(auto-inc Locks
)是一种特殊的表级锁,专门针对事务插入AUTO_INCREMENT
类型的列,每每就是主键列。能够保证主键的值自增是“原子操做”,不会出现一致性、惟一性问题。
InnoDB存储引擎有以上3种行锁算法。以上3种,都是实如今索引上的。
记录锁(Record Lock)老是会去锁住索引记录。 假如没有任何一个索引,那么InnoDB会锁住隐形建立的那个主键。
注意:这里锁的是索引,不必定只是主键索引哦,还多是二级普通索引。
顾名思义,它会封锁索引记录中的“缝隙”,让制其余事务在“缝隙”中插入数据。 它锁定的是一个不包含索引自己的范围。
例如如下索引数据:
间隙锁(Gap Lock)
能够锁的将是如下范围
具体的范围还要根据查询条件不一样而定。 间隙锁开启的事务隔离级别是 Repeatable Read
,若是把数据库事务级别降为Read Committed
(默认是 Repeatable Read
),间隙锁则会自动失效。
Next-Key Lock
能够说是记录锁(Record Lock
)和间隙锁(Gap Lock
)的组合,既封锁了"缝隙",又封锁了索引自己。
仍是上面的索引数据:
临键锁(Next-Key Lock)
锁住的范围将是:
Next-key Lock
在索引具备惟一性的时候,例如主键索引的数据,将会降级为记录锁(Read Lock)
,以增长并发性。 例如:
T1 T2
BEGIN; |
select * From T |
where id = 5 for update |
---------------------------------------------------------------
| BEGIN;
| Insert into t (4, xx);
---------------------------------------------------------------
| COMMIT
|
----------------------------------------------------------------
COMMIT |
|
|
-----------------------------------------------------------------
复制代码
以上状况,就会把Next-key Lock
降级为记录锁(Read Lock)
No Reaptable Read
)和幻读(Phantom Problem
)有些很权威的书中认为这俩是同一个概念,例如:<<MySQL技术内幕 InnoDB存储引擎>>。 可是就目前网络上的众多总结和我的见解,认为区别以下:
不可重复读
:修改。在同一个事务中,主要是说屡次读取一条记录, 发现该记录中某些列值被修改过。 幻读
:增长或者删除。在同一个事务中,同一条彻底相同的查询语句返回的结果集行数不一样。
参考:stackoverflow.com/questions/1…
认真的说,多版本并发控制 MVCC
(读)和 临键锁 Next-Key Lock
(写)共同解决了幻读
问题。
关于MVCC的原理,就是每份数据会有快照,事务中读取数据(简单的select xxx from
,select xx from xx for update
或者select xx from xxx in share mode
不行)的时候,若是数据被锁住了,就读之前留下的快照数据。在此不过多赘述了。
如下为多版本并发控制原理图
MVCC
只在Read Committed
和Repeatable Read
下会开启。可是在这两种隔离级别下对于快照指定的数据定义不一样。
在Read Committed
下,MVCC
读取的是被锁定数据的最新的一份数据。 在Repeatable Read
下,MVCC
读取的是事务刚开始时候的数据。
互联网技术窝
或者加微信共同探讨交流: