mysql锁(2)
上一篇文章:https://www.nasuiyile.cn/160.html
以下的锁都是innodb才有的
间隙锁(gap锁)
当使用范围查询的时候,会给满足组条件的内容进行加锁,比如:
update employee set name='123' where id>3 and id<7;
以上sql语句执行的时候,就会把3到7中间的内容进行加锁
锁定一个范围,不会阻塞其他的gap锁,但会阻插入间隙锁
间隙锁基于非唯一索引
(包括主键),它锁定一段范围内的索引记录
。间隙锁基于下面将会提到的Next-Key Locking
算法,请务必牢记:使用间隙锁锁住的是一个区间,而不仅仅是这个区间中的每一条数据。
记录锁
是锁住记录,锁住索引的记录,而不是真正的数据记录,顾名思义,记录锁就是为某行记录加锁,它封锁该行的索引记录
:
- 所示非主键索引,会在索引记录上枷锁后,在去主键索引上加锁
- 表上没有索引,会隐藏的主键索引上加上锁
- 如果要锁的列没有索引,进行全表记录枷锁
临键锁(next-key)
Next-key可以理解为一种特殊的间隙锁,也可以理解为一种特殊的算法.通过临键锁可以解决幻读的问题.每个数据航上的非唯一索引列都会存在一把临键锁,当摸个失误持有该数据行的临键锁时,会锁住一段左开右闭的区间.需要强调的是innodb中行级锁时基于索引实现的,临键锁值与非唯一索引有关,在唯一索引列(包括主键)上不存在临键锁
临键锁是记录锁与间隙锁的组合,它包含的范围既包含索引记录,又包含索引区间
在根据非唯一索引对记录进行update/for update(间隙锁) /LOCK IN SHARE MODE(共享锁)时,innodb会获取该记录行的临键锁,并同时获取该记录行下一个区间的间隙锁
临键锁的主要目的是为了避免幻读,如果把事务的隔离界别设置为提交度,临键锁也会失效(只存在RR也就是已提交读这个隔离级别),但innodb只在一定程度上面避免了幻读,没有真正解决幻读
意向锁
表锁如何和行锁共存
举个例子事务A锁住表中的一行,事务b锁住了整个表
单马上就有一个问题,事务a既然锁住了一行,其他事务就不可能修改这一行.与事务b锁住了一整个表形成了冲突.所以没有意向锁的时候,行锁与表锁之间共存就会出现问题
有了意向锁之后前面例子中的事务A在申请行锁(写锁)之前,数据库会自动先给事务A申请的表的意向排它锁.当事务b去申请表的写锁时,就会失败,因为表上有意向排它锁知乎事务b申请表的写锁的时候会被阻塞.
意向所的作用是:
当一个事物在需要获取资源的锁定时,如果该资源已经被排它锁占用,则数据库会自动给该事物申请一个该表的意向锁.如果自己需要一个共享锁定,就申请一个意向共享锁,如果需要的是某行或者某些行的排它锁定,则申请一个意向排他锁.
意向所是表还是行锁
意向锁是表级别的锁,原因如下
当我们需要给一个加表锁的时候,我们需要根据意向锁判断表中有没有数据航被锁定,以确定是否能成功.如果意向锁是行锁,那么我们就得遍历表中所有数据来进行判断.如果意向锁是表锁,则我们直接判断一次就真的表中是否有数据被锁定了
冲突性
IX 意向排它锁,IS 意向共享锁,X 排它锁,S 共享锁
x | IX | S | IS | |
---|---|---|---|---|
X | 冲突 | 冲突 | 冲突 | 冲突 |
IX | 冲突 | 兼容 | 冲突 | 冲突 |
S | 冲突 | 冲突 | 兼容 | 兼容 |
IS | 冲突 | 兼容 | 兼容 | 兼容 |
意向插入锁
意向插入锁是一种通过insert插入之前操作设置的间隙锁定。此锁发出插入意图的信号,如果是多个事务未插入间隙中的相同位置,则无需等待插入到同一行所有间隙中的多个事务。
在多十五同时写入不同数据值同意所有间隙的时候,并不需要等待其他事务完成,不会发生锁等待
假设一个值记录索引包含4和7不同的事物分别插入6和6,每个事务都会产生一个加在4-7之间的意向插入锁,获取在插入行上的排它锁,但是不会被相互所住,因为数据行并不冲突。
插入意向锁不会组织任何锁,对插入的记录会持有一个记录锁
自增锁
自增锁是mysql一种特殊的锁,如果表中存在自增字段,mysql便会自动维护一个自增锁
他是一种特殊的表级别锁,专门正对事务插入自增类型的列。最简单的情况,如果事务正在往表中插入记录,所有其他食物的插入必须等待,一百年第一个事务插入的行,是连续主键值