mysql锁技术讨论

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

mysql 常见锁问题分析

1 参考资料

2 要明确的概念

  • 不可重复读和幻读的区别
  • 快照读和当前读
  • 事务的隔离级别
  • record lock、gap lock、next-key lock

2.1 不可重复读和幻读的区别

select数据的不变性可以细分成2部分

  • 第一部分就是:对原有数据的不可修改性,如update delete,通过行锁锁住记录就可以实现不可修改
  • 另一部分就是:对于新增数据的限制,这时候就不能通过行锁来解决了,这时候就需要通过gap lock来解决

如果仅仅满足了第一部分可以叫可重复读,如果也满足了第二部分就算是解决了幻读的问题。

而目前mysql的innodb数据库引擎实现的Repeatable reads不仅仅解决了上述的第一部分也解决第二部分,即Repeatable reads级别下已经解决了幻读问题。

2.2 快照读和当前读

快照读: 如普通的select * from t where id>=6;采用MVCC(多版本并发控制)仅仅读取该事务号及其之前的数据

当前读:如select * from t where id>=6 for update;读取的是最新提交的事务号及其之前的数据

2.3 事务的隔离级别

Read committed 的隔离级别:只能读到别人已提交的数据,未提交的数据读不到,RC的隔离级别存在不可重复读和幻读的现象,即在同一个事务内,第一次select查询出一定结果后,别的客户端此时又修改了源数据和提交了新的数据,第二次select是可以查出修改后的数据和新提交的数据的,这就导致了和第一次select的数据不一致的问题

Repeatable reads 的隔离级别:比起Read committed,解决了不可重复读的现象,而mysql的innodb数据库引擎实现的Repeatable reads也解决了幻读问题。

  • 对于快照读中的幻读(即select * from t where id>=6出现的幻读)采用的解决方式是采用MVCC(多版本并发控制)
  • 对于当前读中的幻读(即select * from t where id>=6 for update出现的幻读)采用的解决方式是gap lock

3 问题分析

如下的一个事务并发执行

start transaction;
DELETE FROM t WHERE id =6;
INSERT INTO t VALUES(6);
commit;

就隔离级别和id唯一索引、id非唯一索引组合等情况展开分析以下内容:

  • 使用了什么锁?阻塞情况?
  • 是否会出现死锁?

3.1 Read committed和唯一索引id

3.2 Read committed和非唯一索引id

3.3 Repeatable reads和唯一索引id

创建表的sql:

create table m (
    id int ,
    primary key (id)
);

填充数据 1、2、6、8

insert into m values(1),(2),(6),(8);

步骤1:客户端A

start transaction;
delete from m where id =6;

步骤2:客户端B

start transaction;
delete from m where id =6;

步骤3:客户端A

insert into m value(6);

步骤4:客户端B

insert into m value(6);

3.3.1 删除一个已存在的值

其中delete from m where id =6语句会对索引中id=6的记录加上next-key lock,但是由于where id=6的查询条件结果是确定的,即不会出现幻读的情况,所以仅仅对id=6的记录加上一个record lock即可,即由next-key lock降级到了record lock。

所以当客户端A执行完毕步骤1后,客户端B执行步骤2的时候,由于已经存在了record lock,所以客户端B会被阻塞,等待客户端A的record lock的释放,现象如下:

输入图片说明

3.3.2 删除一个不存在的值

上述的id=6全部换成id=5,即客户端A执行delete from m where id=5;由于记录不存在,所以只会在索引(2,6)区间中加上gap lock。此时如果客户端B也同样执行delete from m where id=5,由于记录不存在,也只会在索引(2,6)区间中加上gap lock,这两个gap lock之间不冲突,可以同时存在。

此时客户端执行insert into m value(5),因为insert语句会添加一个 insert intention gap lock(见官方文档insert intention gap lock),其中这个锁和gap lock是可以冲突的,此时插入的数值5刚好在上述客户端B创建的gap lock锁定的区间中,所以此时客户端A是要等待客户端B释放gap lock的,即被阻塞了

此时客户端B同样执行insert into m value(5),也会因为客户端A创建的gap lock而造成阻塞,此时客户端A、B相互阻塞造成死锁,现象如下

输入图片说明

发生死锁后,innode引擎自动检测到死锁,会让一个进行释放,另一个得到执行

3.4 Repeatable reads和非唯一索引id

创建表的sql:

create table t (
    id int ,
    key (id)
);

填充数据 1、2、6、8

insert into t values(1),(2),(6),(8);

步骤1:客户端A

start transaction;
delete from t where id =6;

步骤2:客户端B

start transaction;
delete from t where id =6;

步骤3:客户端A

insert into t value(6);

步骤4:客户端B

insert into t value(6);

3.4.1 删除一个已存在的值

其中delete from t where id =6语句会对索引中id=6的记录加上next-key lock,即id=6的记录本身加上record lock,同时(2,6)、(6,8) 这两个区间会加上gap lock。

所以当客户端A执行完毕步骤1后,客户端B执行步骤2的时候,由于已经存在了record lock,所以客户端B会被阻塞,等待record lock的释放,现象如下:

客户端B被阻塞

3.4.2 删除一个不存在的值

假如上述的id=6全部换成id=5,执行 delete from t where id =5的话,即delete 一个不存在的值,则只会对索引的(2,6)区间加上gap lock。客户端B就不会阻塞,同样的在索引(2,6)区间加上gap lock,gap lock之间不冲突的,即这时的客户端B不会阻塞。

这时客户端A执行 insert into t value(5)会阻塞,因为insert语句会添加一个 insert intention gap lock(见官方文档insert intention gap lock),其中这个锁和gap lock是可以冲突的,此时插入的数值5刚好在上述客户端B创建的gap lock锁定的区间中,所以此时客户端A是要等待客户端B释放gap lock的,即被阻塞了

输入图片说明

而客户端A执行的insert into t value(5)所加入的insert intention gap lock是不会和自己创建的gap lock冲突的,即如果没有其他gap lock的话,客户端A往自己创建的gap lock区间中insert值是不被阻塞的

输入图片说明

假如此时客户端B同样执行insert into t value(5)操作,则会因为客户端A创建的gap lock而等待,此时客户端A B在相互等待对方释放gap lock,造成死锁,现象如下:

输入图片说明

发生死锁后,innode引擎自动检测到死锁,会让一个进行释放,另一个得到执行

4 案例演示当前读和快照读

创建表的sql:

create table t (
    id int ,
    key (id)
);

填充数据 1、2、6、8

insert into t values(1),(2),(6),(8);

步骤1:客户端A

start transaction;
select * from t where id>=6;

步骤2:客户端B

start transaction;
insert into t value(10);
commit;

步骤3:客户端A

select * from t where id>=6;
select * from t where id>=6 for update;

步骤3中是第一个select是看不到客户端B新增的数据的,因为他是快照读,读取的是该事务号及其之前的数据

步骤3中的第二个select是可以看到客户端B新增的数据的,因为它是当前读,读取的是最新提交的事务号及其之前的数据

现象如下:

输入图片说明

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2天前
|
SQL 关系型数据库 MySQL
MySQL底层概述—10.InnoDB锁机制
本文介绍了:锁概述、锁分类、全局锁实战、表级锁(偏读)实战、行级锁升级表级锁实战、间隙锁实战、临键锁实战、幻读演示和解决、行级锁(偏写)优化建议、乐观锁实战、行锁原理分析、死锁与解决方案
MySQL底层概述—10.InnoDB锁机制
|
1天前
|
关系型数据库 MySQL 网络安全
如何排查和解决PHP连接数据库MYSQL失败写锁的问题
通过本文的介绍,您可以系统地了解如何排查和解决PHP连接MySQL数据库失败及写锁问题。通过检查配置、确保服务启动、调整防火墙设置和用户权限,以及识别和解决长时间运行的事务和死锁问题,可以有效地保障应用的稳定运行。
40 25
|
4月前
|
SQL 关系型数据库 MySQL
MySQL 锁
MySQL里常见的几种锁
82 3
|
27天前
|
存储 关系型数据库 MySQL
MySQL进阶突击系列(06)MySQL有几种锁?| 别背答案,现场演示一下
本文详细解析了MySQL InnoDB存储引擎的锁机制,涵盖读锁、写锁、意向锁、记录锁、间隙锁和临键锁等8种锁类型。重点探讨了不同锁类型的加锁与释放方式,以及事务并发场景下的实战验证。通过具体示例,展示了在不同情况下锁的行为及其对事务的影响。文章还特别强调了锁的作用范围主要是索引,并解释了锁如何影响数据的读写操作。最后总结了并发事务中加锁规则,帮助读者深入理解MySQL的锁机制。
|
2月前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
126 1
|
3月前
|
监控 前端开发 Java
【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL
该文档介绍了基于Java后端和Vue3前端构建的管理系统的技术栈及功能模块,涵盖管理后台的访问、登录、首页概览、API接口管理、接口权限设置、接口监控、计费管理、账号管理、应用管理、数据库配置、站点配置及管理员个人设置等内容,并提供了访问地址及操作指南。
|
3月前
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
238 3
|
4月前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
272 1
|
4月前
|
XML 关系型数据库 MySQL
MySQL 导出某些数据的技术详解
MySQL 导出某些数据的技术详解
229 2
|
4月前
|
关系型数据库 MySQL Java
MySQL数据锁:Record Lock,Gap Lock 和 Next-Key Lock
本文基于 MySQL 8.0.30 版本及 InnoDB 引擎,深入解析三种行锁机制:记录锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-key Lock)。记录锁锁定索引记录,确保事务唯一修改;间隙锁锁定索引间的间隙,防止新记录插入;临键锁结合两者,锁定范围并记录自身,有效避免幻读现象。通过具体示例展示了不同锁的作用机制及其在并发控制中的应用。
490 2