2024年最新InnoDB 锁机制_innodb锁机制(1),Golang工程面试问题

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

二. innoDB 锁应用
一致性非锁定读 (consist nonblocking read)

一致性非锁定读,指通过行多版本控制(MVCC)方式读取数据库中的行数据。如果读取的行正在执行DELETEUPDATE,该读操作也不会阻塞等待锁释放,而是直接读取行的快照数据。快照是指当前行之前版本的数据,通过 undo 段实现。因为 undo 段用来事务回滚数据,所以快照本身并不会带来额外开销
在事务隔离级别 READ COMMITTEDREPEATABLE READ 下,InnoDB 使用一致性非锁定读。

  • 前者总是读取行的最新一份快照数据, 这份快照数据可能是其他事务刚刚提交的,所以叫读已提交
  • 后者总是读取事务开始时的行数据版本,因此在一个事务内多次读取的数据相同,所以叫可重复读
一致性锁定读

某些情况下,用户需要显式的对数据库读操作的行进行加锁来保证逻辑上的一致性,就要执行 SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE。对于一致性非锁定读,即使行上由其它事务进行锁定读,也可以正常进行读取。

自增列与锁

主键经常采用自增长方式,每个含有自增长值的表都有一个自增长计数器,当对含有自增长计数器的表插入时,会进行 AUTO-INC Locking。是一种表级别锁。只是这个锁不是在事务提交后才释放,而是完成对自增长值的插入操作后立刻释放。所以,对于像INSERT ... SELECT 的大数据量插入会影响插入性能,因为另一个事务中的插入会阻塞。但从 Mysql 5.1.22 后,提供了参数 innodb_autoinc_lock_mode 来控制自增长模式。

三. InnoDB 锁算法

InnoDB 有三种行锁算法

  • Record Lock : 单个行记录上的锁, 锁主键
  • Gap Lock : 间隙锁,锁定一个范围,但不锁行本身
  • Next-Key Lock : Record Lock + Gap Lock 锁定一个范围,且锁定行本身(左闭右开区间)
    比如一个表里有4个索引(10,11,13,20),则可能被 Next-Key Locking 的索引区间是(负无穷,10], (10,11], (11,13],(13,20],(20,正无穷]。因为每个索引上的 Next-Key Lock 都是之前索引的区间 + 索引本身

InnoDB 对于行的锁定都是采用 Next-Key Lock ,这种锁锁定的不仅是单个行,而且包括一个范围,它的设计目的是为了解决幻读问题。但是当查询的索引是唯一索引时,InnoDB 会把 Next-Key Lock 降级为 Record Lock,即只锁索引本身,而不锁区间范围。比如:

  • 主键也是唯一索引, 锁降级
-- 创建一个表, 主键a, 有1,2,5 三个值
Create Table t (a INT Primary Key);
insert into t SELECT 1;
insert into t SELECT 2;
insert into t SELECT 5;

-- 事务1
select \* from t where a = 5 for update;  -- 锁定主键5

-- 事务2
insert into t select 4; -- 可以成功,因为主键是唯一索引,降级为 record lock, 只索索引

  • 辅助索引除了在索引上加 next-key lock,还会在与下一个索引的区间上加 gap lock。导致下列操作失败
create table t (a INT primary key, b int key);
insert into t SELECT 1,1;
insert into t SELECT 3,1;
insert into t SELECT 5,3;
insert into t SELECT 7,6;

-- 事务1
-- b 是辅助索引,在副主索引上的锁区间为 (1,3] 和 (3,6) , Next-Key Lock + gap lock
-- b = 3 对应 a = 5, a 是主键, 索引加的是 record lock,只锁 a= 5 这个值
select \* from t where b = 3 for update; 

-- 事务2
select \* from t where a = 5 lock in share mode; -- 不能执行,因为行锁 a = 5 存在
insert into t select 4,2; -- 不能执行,a = 4 可以,但 b = 2 在 (1,3] Next-Key Lock 内
insert into t select 6,5; -- 不能执行, a = 6 可以,但 b = 5 在 (3,6) gap lock 内

四. Phantom Problem

默认的事务隔离级别 REPEATABLE READ 下, InnoDB 采用 Next-Key Lock 避免产生幻读。所谓幻读,是指同一事务下,连续两次 select 返回的数据不同,第二次 select 可能返回之前不存在的行。 比如对于上面的表 t, 由 1,2,5 三个值组成 :

  • 事务1执行 select * from t where a>2 for update; 只返回5一个值。
  • 此时事务2执行insert into t select 4 如果执行成功的话, 事务1再次执行 select ... a>2 会返回4,5两个值,造成幻读。

因此 innoDB 采用 Next-Key Lock,在 a>2 的条件上的锁范围是 (2,正无穷) , 这样事务2的插入不会成功。但是在 READ COMMITED 级别下,对于 a>2 扫描到的索引 2 和 5 加的是 record lock, 只锁行本身,这会导致事务2插入成功,事务1产生幻读。

五. 锁带来的问题
1. 脏读

脏数据是指事务未提交的数据,读到脏数据,指一个事务读到了另一个事务未提交的数据,违反了数据库的隔离性。发生脏读的条件是事务隔离级别设置成了 READ UNCOMMITED,这种情况不常发生, 因为现在的数据库至少设置成 READ COMMITED

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

/618658159)**

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值