(八)索引失效,间隙锁,加锁规则

16 一些索引失效情况

  1. 条件字段函数操作
  2. 隐式类型转换

如 select * from tradelog where tradeid=110717;

如果tredeid是字符串类型,那么在比较时会隐性地将字符串转为数字,也就不会走索引来

  1. 隐式字符编码转换

当两个表的字符集不同,在关联时作字符集转换实际也是一个隐性类型转换,此时也不会走索引

17 间隙锁

为了避免幻读带来的数据不一致问题,当执行 select * from t where d=5 for update 的时候,就不止是给数据库中已有的 6 个记录加上了行锁,还同时加了 7 个间隙锁。

也就是说这时候,在一行行扫描的过程中,不仅将给行加上了行锁,还给行两边的空隙,也加上了间隙锁。(因此对于有索引和无索引的加锁情况是不同的,无索引的会对所有扫描的行加next-key lock,几乎等于锁表;有索引的

跟间隙锁存在冲突关系的,是“往这个间隙中插入一个记录”这个操作。间隙锁之间都不存在冲突关系。

间隙锁和行锁合称 next-key lock,每个 next-key lock 是前开后闭区间。也就是说,我们的表 t 初始化以后,如果用 select * from t for update 要把整个表所有记录锁起来,就形成了 7 个 next-key lock,分别是 (-∞,0]、(0,5]、(5,10]、(10,15]、(15,20]、(20, 25]、(25, +supremum]。

  • 间隙锁导致死锁问题

如执行以下逻辑

begin;select * from t where id=N for update;
/*如果行不存在*/
insert into t values(N,N,N);
/*如果行存在*/
update t set d=N set id=N;
commit;

在并发情况下
在这里插入图片描述

  1. session A 执行 select … for update 语句,由于 id=9 这一行并不存在,因此会加上间隙锁 (5,10);
  2. session B 执行 select … for update 语句,同样会加上间隙锁 (5,10),间隙锁之间不会冲突,因此这个语句可以执行成功;
  3. session B 试图插入一行 (9,9,9),被 session A 的间隙锁挡住了,只好进入等待;
  4. session A 试图插入一行 (9,9,9),被 session B 的间隙锁挡住了。

18加锁规则

  1. 原则 1:加锁的基本单位是 next-key lock。next-key lock 是前开后闭区间。
  2. 原则 2:查找过程中访问到的对象才会加锁。
  3. 优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
  4. 优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值