本文将跟大家聊聊InnoDb的锁,以及如何分析和解决死锁问题,希望对大家有帮助哈 。
- 为什么需要加锁呢?
- InnoDB的七种锁介绍
- 一条SQL是如何加锁的
- RR隔离级别下的加锁规则
- 如何查看事务加锁情况
- 死锁案例分析
在日常生活中,如果你心情不好想静静,不想被比别人打扰,你就可以把自己关进房间里,并且反锁 。同理,对于MySQL数据库来说的话,一般的对象都是一个事务一个事务来说的 。所以,如果一个事务内,正在写某个SQL,我们肯定不想它被别的事务影响到嘛?因此,数据库设计大叔,就给被操作的SQL加上锁 。
专业一点的说法: 如果有多个并发请求存取数据,在数据就可能会产生多个事务同时操作同一行数据 。如果并发操作不加控制,不加锁的话,就可能写入了不正确的数据,或者导致读取了不正确的数据,破坏了数据的一致性 。因此需要考虑加锁 。1.1 事务并发存在的问题
- 脏读:一个事务A读取到事务B未提交的数据,就是脏读 。
- 不可重复读:事务A被事务B干扰到了!在事务A范围内,两个相同的查询,读取同一条记录,却返回了不同的数据,这就是不可重复读 。
- 幻读:事务A查询一个范围的结果集,另一个并发事务B往这个范围中插入/删除了数据,并静悄悄地提交,然后事务A再次查询相同的范围,两次读取得到的结果集不一样了,这就是幻读 。
为了更通俗易懂一点,还是给大家举个例子吧,虽然东西挺简单的 。假设现在有表结构:
CREATE TABLE `account` (`id` int(11) NOT NULL,`name` varchar(255) DEFAULT NULL,`balance` int(11) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `un_name_idx` (`name`) USING BTREE) ENGINE=InnoDB DEFAULT CHARSET=utf8;insert into account(id,name,balance)values (1,'Jay',100);insert into account(id,name,balance)values (2,'Eason',100);insert into account(id,name,balance)values (3,'Lin',100);
在READ-UNCOMMITTED(读未提交) 隔离级别下,假设现在有两个事务A、B:- 假设现在Jay的余额是100,事务A正在准备查询Jay的余额
- 这时候,事务B先扣减Jay的余额,扣了10
- 最后A 读到的是扣减后的余额
文章插图
手动验证了一把,流程如下:
文章插图
由上图可以发现,事务A、B交替执行,事务A被事务B干扰到了,因为事务A读取到事务B未提交的数据,这就是脏读 。这是因为在读未提交的隔离级别写操作,并没有对SQL加锁,因此产生了脏读这个问题 。
我们再来看下,在串行化隔离级别下,同样的SQL执行流程,是怎样的?
文章插图
为啥会阻塞等待超时呢?这是因为串行化隔离级别下,对写的SQL加锁啦 。我们可以看下加了什么锁,命令如下:
SET GLOBAL innodb_status_output=ON; -- 开启输出SET GLOBAL innodb_status_output_locks=ON; -- 开启锁信息输出SHOW ENGINE INNODB STATUS
锁相关的输出内容如下:文章插图
我们可以看到了lock_mode X locks rec but not gap,它到底是一种什么锁呢?我们一起来学习下InnoDB的七种锁 。
2. InnoDB的七种锁介绍
文章插图
2.1 共享/排他锁InnoDB呢实现了两种标准的行级锁:共享锁(简称S锁)、排他锁(简称X锁) 。
- 共享锁:简称为S锁,在事务要读取一条记录时,需要先获取该记录的S锁 。
- 排他锁:简称X锁,在事务需要改动一条记录时,需要先获取该记录的X锁 。
推荐阅读
- C语言入门算法丨冒泡排序算法详解!绝不摆烂
- 适合中国家庭的国产两厢推荐
- 如何把红茶泡好喝,咖啡红茶怎么泡
- 职业教育|职业教育想要振兴,需要改变两大关键因素
- 滇红茶耐泡,凤庆滇红茶泡法
- 卧室有两个窗户对风水有利吗?
- 卧室有两个门对我们有什么影响
- 两个动作看透你 准确率达99%!
- Windows操作系统|Win11大更新就绪:微软详解重要新功能 CPU效率暴增、全新任务管理器
- 脂肪怎么排出,教你两招懒人方法