MySQL之Lock探索(二)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 联动贴:http://blog.itpub.net/29510932/viewspace-1814690/------------------------------------------------------------------------------接前文...
联动贴: http://blog.itpub.net/29510932/viewspace-1814690/

---------------------------- --------- -----------------------------------------接前文------------------------------------------------------------------------------------------------
前文写了一些锁相关的东西,后半篇写一些各种情况下的锁的情况
-------------------------------------------------------------------------------正文------------------------------------------------------------------------------------------------
测试方法:两个session分别执行简单的insert/delete/update语句,模拟锁的情况
测试环境:官方MySQL-5.6.26,隔离级别REPEATABLE-READREAD COMMITTED
测试内容:测试表student,试验分为六组,RR,RC两种隔离级别唯一索引,非唯一索引,无索引三种情况数据和表结构如下(根据实验的要求,可能简单改一下数据)


1.RR隔离级别,非唯一索引
session1:
delete from student where sid = 10005;
session2:
insert into student values(10006,'se10006');
insert into student values(10008,'se10008');
insert into student values(10010,'se10010');
分析:
从MySQL实现的角度来看,在sid上具备索引,根据MySQL加锁的特点,session1会在索引sid上加上X锁,
但是sid是非唯一索引,如果只对sid=10005这一条记录加锁,并不能阻止其他的事务继续插入sid=10005的数据,从而会误删其他事务插入的sid=10005的数据,
所以MySQL会在10005的前后加上GAP锁(间隙锁),阻止其他事务插入sid处于10005-10007和10007-10009区间的任何数据
加锁的示意图如下

所以10006和10008的数据刚好在GAP锁的范围之内,mysql锁的信息




10010在GAP锁的范围之外(10010既不在10005-10007,也不再10007-10009范围内),所以能够正常的插入


2.RR隔离级别,唯一索引
session1:
delete from student where sid = 10005;
session2:
insert into student values(10006,'se10006');
insert into student values(10008,'se10008');
insert into student values(10010,'se10010');
分析:
从MySQL实现的角度来看,在sid上具备索引,根据MySQL加锁的特点,session1会会在索引sid上加上X锁,
由于sid是唯一索引,所以对与MySQL来说,它能确认在这个索引上,至多只会存在一条数据满足sid=10005
唯一索引本身的特性会阻止其他的事务继续插入sid=10005的数据,从而防止误删其他事务插入的sid=10005的数据

所以MySQL只需要在10005加上X锁,而无需加上GAP锁,锁住10005前后的间隙,所以session2的所有语句都不会阻塞。
加锁的示意图如下

MySQL的信息


3.RR隔离级别,无索引
session1:
delete from student where sid = 10005;
session2:
insert into student values(10004,'se10004');
insert into student values(10008,'se10008');
insert into student values(10010,'se10010');
分析:
从MySQL实现的角度来看,在student表上没有索引,根据MySQL本身的特点,MySQL会自动创建一个隐藏的聚簇索引作为主键,
当delete操作执行时,student表不存在任何索引,所以MySQL会用X锁锁住所有的行,锁的标记位在自动创建的聚簇索引上;
当session2试图修改or操作student表的数据时,无法在聚簇索引上加锁,进行锁等待。
加锁示意图如下

MySQL的信息

可以看到由于不存在索引,session1锁住了整个表的所有行,而session2则在等待X锁的释放,X锁是加在自动生成的聚簇索引"GEN_CLUST_INDEX"上。
session2的其他语句有同样的效果,图略去。

4.RC隔离级别,无索引
session1:
delete from student where sid = 10005;
session2:
insert into student values(10006,'se10006');
insert into student values(10005,'se10005');
分析:RC隔离级别,无索引的情况,session1依然会对表的所有行加上X锁,session2的操作会被阻塞
加锁情况


然而实际情况如下


这是因为MySQL在处理这种锁的情况的时候,会去过滤实际需要锁定的行(sid=10005),然后释放掉不需要的那些行的锁,实际上对所有行的加锁操作还是存在的;

5.RC隔离级别,非唯一索引
session1:
delete from student where sid = 10005;
session2:
insert into student values(10006,'se10006');
update student set sname = '1111' where sid = 10005;
update student set sname = '1111' where sid = 10006;

分析:
RC隔离级别,非唯一索引的情况,session1只会对表的符合条件的行加上X锁,这里补上两个update来看一下X锁的情况
session2的执行情况,可以看到同样在操作10005的时候, 由于锁等待,对10005的update操作被阻塞了,但是对10006的操作是正常的
加锁情况同4

锁情况


6.RC隔离级别,唯一索引
session1:
delete from student where sid = 10005;
session2:
insert into student values(10006,'se10006');
update student set sname = '1111' where sid = 10005;
update student set sname = '1111' where sid = 10006;

分析:
同情况5,只会对符合条件的行加上X锁。
加锁情况同4

7.RR隔离级别
这个情况单独写出来:当delete语句指定的行,在表当中找不到的时候,会有特殊的处理
表内容小改:

session1:
delete from student where sid = 10007;
session2:
insert into student values(10006,'se10006');
insert into student values(10008,'se10008');
insert into student values(10010,'se10010');
分析:student表存在唯一索引,在这种情况下,因为表中不存在这一行数据,所以MySQL会找到>10007且不符合条件的第一行数据,加上X锁,然后在这一条数据的前面加上GAP锁
加锁示意图

mysql的信息



当存在非唯一索引时,与唯一索引是一样的加锁策略,
在无索引的情况下,则是锁住表的全部行。

PS:写在最后,产生死锁的原因,是因为两个事务都需要同时持有多个锁, 但是他们分别持有对方需要的一部分锁。

---------------------------------------------------------------------------------结尾----------------------------------------------------------------------------------------------
前几个试验的时候,session2的insert貌似选的不是很合理,不过实际上GAP锁确实是有加持,在后面的第七种情况里面也能看出来
终于填完了锁的坑,接下来还有metadata lock, index_merge,还有啥来着......太多了....._(:з」∠)_
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
关系型数据库 MySQL 分布式数据库
PolarDB MySQL版并行查询技术探索与实践
PolarDB MySQL版并行查询技术探索与实践 PolarDB MySQL版在企业级查询加速特性上进行了深度技术探索,其中并行查询作为其重要组成部分,已经在线稳定运行多年,持续演进。本文将详细介绍并行查询的背景、挑战、方案、特性以及实践。
391 2
|
SQL 关系型数据库 MySQL
MySQL调优之大表处理探索那些事
MySQL调优之大表处理探索那些事
291 0
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
1224 2
|
SQL 关系型数据库 MySQL
Mysql Lock Wait
Mysql Lock Wait
284 0
|
存储 SQL 关系型数据库
【MySQL技术内幕】6.1-锁、lock和latch
【MySQL技术内幕】6.1-锁、lock和latch
305 0
|
存储 SQL 关系型数据库
【MySQL】探索MySQL存储过程的魔力,初学者的数据库编程秘笈(内含实战SQL脚本)上
【MySQL】探索MySQL存储过程的魔力,初学者的数据库编程秘笈(内含实战SQL脚本)
548 2
|
存储 SQL 关系型数据库
【MySQL】探索MySQL存储过程的魔力,初学者的数据库编程秘笈(内含实战SQL脚本)下
【MySQL】探索MySQL存储过程的魔力,初学者的数据库编程秘笈(内含实战SQL脚本)
229 1
|
关系型数据库 MySQL 数据库
MySQL报错:Lock wait timeout exceeded; try restarting transaction
MySQL报错:Lock wait timeout exceeded; try restarting transaction
1545 0
|
SQL 关系型数据库 MySQL
MySQL报错:1205 Lock wait timeout exceeded; try restarting transaction处理
MySQL报错:1205 Lock wait timeout exceeded; try restarting transaction处理
941 0
|
SQL 关系型数据库 MySQL
【MySQL异常】MySQL事务锁问题----lock wait timeout exceeded; try restarting transaction
【MySQL异常】MySQL事务锁问题----lock wait timeout exceeded; try restarting transaction
1171 0

推荐镜像

更多