当前位置: 首页 > news >正文

详解MySQL的并发控制

目录

1.概述

2.事务

2.1.什么是事务

2.2.事务的隔离级别

2.2.1.三种数据一致性问题

2.2.2.四种隔离级别

2.3.如何设置隔离级别

3.锁

3.1.锁与事务的关系

3.2.分类

3.3.表锁

3.3.1.概述

3.3.2.读锁

3.3.3.写锁

3.3.4.保护机制

3.4.行锁

3.4.1.概述

3.4.2.什么是MVCC

3.4.3.mvcc的使用

3.4.4.间隙锁

3.4.5.行锁变表锁 


1.概述

所谓的并发控制,就是规避多个会话并发访问数据库带来的诸如脏数据之类的数据一致性问题,MySQL中提供了一系列的机制让我们可以去进行并发控制。

本质上来说MySQL就是用的两种锁来进行并发控制,一种是表锁,锁住整张表;一种是行锁,锁住某个数据行。

平时我们使用的时候,很少会直接去操作锁,因为MySQL已经帮我们封装的很好了,直接用innodb引擎+事务就能很好的进行并发控制,事务底层其实依赖的就是行锁。

本文会先聊事务、再聊表锁、行锁,但其实总的来说MySQL进行并发控制,就是行锁和表锁,事务的底层用的就是行锁,只是事务太重要了所以单独拎出来作为一个独立的章节聊。

2.事务

2.1.什么是事务

注意:只有innodb引擎是支持事务的,所以本文与事务相关的讨论,默认都是在innodb引擎下。

在实际使用中,会存在这样一类场景,我们希望几条SQL要么同时执行成功,要么同时失败,不能有的成功,有的失败。

比如网购下单,生成订单、扣减库存两条SQL,必须保证要么全部成功,要么全部失败,不能说生成订单成功,但是扣减库存失败了,或者说扣减库存成功但是生成订单失败了,以上任何一种情况都是会产生脏数据的。如果两者中有一者失败,另外一个也需要跟着执行不成功,从而保证数据的正确性。

事务就是为了满足将多条捆绑在一起,同成功,同失败而出现的。人们在实现事务过程中,发现事务要实现上面我们说的效果,那么就必须实现四点:

  • 原子性(Atomicity)
  • 一致性(Consistent)
  • 隔离性(Isolation)
  • 持久性(Durable)

也就是大名鼎鼎的ACID,很多地方称其为事务的四大特性。

1.原子性:

事务是一个原子操作单元,其对数据的修改,要么全部执行,要么全部不执行。

2.一致性:

数据库中的数据总是从一个状态到另一个状态,不能存在中间状态。继续以网购下单为例,一开始的数据库中的数据为A状态,执行完事务,扣减库存、新增订单后的数据状态为B状态,数据库只能由A到B,不能出现诸如扣了库存,没生成订单,或者生成了订单,没扣库存这样的中间状态。

3.隔离性:

一个事务在提交之前,其所做的修改对其它事务来说是不可见的。不保证隔离性会产生脏数据,这个很好理解,举个例子:

A的银行账户有400,有两个事务,彼此之间数据可见,也就是一个事务修改数据,不管提没提交其他事务都看得见。

事务1,A向B转200:

  • A的账户扣减200
  • B的账户新增200

事务2,A向C转200:

  • A的账户扣减200
  • C的账户新增200

如果在事务1中的1、2步的时间间隙内事务2间插执行完毕,那么在事务1第2步执行前A的账户中已经被扣减了两次200,余额为0,C的账户中多了200。

这时候如果在事务1的第2步中出错了、回滚,那么A的账户又会回到事务1第一步执行之前的状态,也就是A的账户又恢复成了400。最后C的账户平白无故多了200。

4.持久性:

事务完成后,其对数据的修改是永久的,即使系统断电、重启,也不会变。

2.2.事务的隔离级别

2.2.1.三种数据一致性问题

在没有隔离性的情况下,事物之间会出现3种数据一致性问题:

  1. 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
  2. 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
  3. 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

2.2.2.四种隔离级别

隔离级别可理解为,隔离性的严格度,MySQL并不是固定死了各个事务间就是不可读的,而是规定了各种强度的隔离级别。

观察上面3种数据一致性问题就会发现,解决它们需要的隔离性是递增的,MySQL一共给出4种隔离级别,隔离性也是递增的,对应解决以上3个问题,有3种,加上1种3种问题都能覆盖解决的:

  1. Read Uncommitted(读未提交):最低的隔离级别,允许一个事务读取另一个事务尚未提交的数据变更。可能导致脏读(Dirty Read)问题。

  2. Read Committed(读已提交):确保一个事务只能读取另一个事务已经提交的数据变更。防止脏读问题,但可能导致不可重复读(Non-repeatable Read)问题。

  3. Repeatable Read(可重复读):确保在同一个事务中多次读取同一数据时,能够得到一致的结果。防止脏读和不可重复读问题,但可能导致幻读(Phantom Read)问题。

  4. Serializable(串行化):最高的隔离级别,强制事务串行执行,确保不会发生脏读、不可重复读和幻读问题。但是并发性能较差,通常不建议在高并发环境中使用。

2.3.如何设置隔离级别

可以在连接字符串中设置隔离级别:

jdbc:mysql://localhost/mydatabase?useSSL=false&characterEncoding=utf8&transactionIsolation=隔离级别

可以通过SQL在会话中设置隔离级别:

SET TRANSACTION ISOLATION LEVEL 隔离级别;

3.锁

3.1.锁与事务的关系

锁是计算机协调多个进程或线程并发访问某一资源的机制,用来解决并发访问带来的数据一致性问题。在数据库中,除传统的计算资源(如CPU、IO、RAM)的争用以外,数据更是会被并发访问的资源。所以MySQL数据库也用锁机制来保证数据并发访问的一致性。

不同的隔离级别底层就是用不同的锁来实现的。

3.2.分类

MySQL的锁可以从两种维度来分,

一个维度是按照锁的是一行,还是锁的是整张表,分为:

  • 行锁
  • 表锁

另一个维度是按照锁的操作是读操作,还是写操作,分为:

  • 读锁
  • 写锁

3.3.表锁

3.3.1.概述

MySQL中innodb引擎和myisam引擎均支持用lock tables指令来锁表。

3.3.2.读锁

读锁,一种共享锁,针对被锁表,所有会话都可以进行读操作,所有会话都无法进行写操作。加锁方和其他客户端的区别是,加锁方直接不允许进行写操作,而其他会话的写操作允许进行,只是会被阻塞挂起。锁解开后,所有挂起的操作线程会去重新争抢资源。

加锁指令:

lock tables 表名 read;

释放锁指令:

unlock tanles;

加锁方不允许进行写操作:

其它客户端的写操作在加锁方释放锁之前都被挂起:

3.3.3.写锁

写锁,排它锁,针对被锁表,加锁方可以读写,其他会话的写操作会直接失败,读操作会被阻塞挂起,解锁以后,被挂起的线程会重新去争抢资源。

加锁指令:

lock tables 表名 write;

其它会话的读操作、写操作在加锁方释放锁之前都被阻塞挂起:

 

3.3.4.保护机制

读锁、写锁中,加锁方都只能读当前被自己锁定的表,这是MySQL的一个保护机制,为的就是强制要求加锁方给出一个说法,到底准备锁多久,不给说法不让走。

3.4.行锁

3.4.1.概述

innodb和myIsam最大的不同有两点,一是支持事务,二是支持行级锁。

3.4.2.什么是MVCC

行锁没有显式的声明办法,而是藏在默认实现中,MVCC 是 MySQL InnoDB 存储引擎的默认并发控制机制,其采用的就是表锁。

并发控制有几种处理方法,

第一种: 基于锁的并发控制,程序员B开始修改数据时,给这些数据加上锁,程序员A这时再读,就发现读取不了,处于等待情况,只能等B操作完才能读数据,这保证A不会读到一个不一致的数据,但是这个会影响程序的运行效率。

第二种:MVCC,每个用户连接数据库时,看到的都是某一特定时刻的数据库快照,在B的事务没有提交之前,A始终读到的是某一特定时刻的数据库快照,不会读到B事务中的数据修改情况,直到B事务提交,才会读取B的修改内容。

MVCC其实就是实现事务的关键,后续会有文章专门深入聊事务的实现,此处暂不展开。

3.4.3.mvcc的使用

首先有一个需要纠正的是,很多地方都说mvcc是通过手动提交来触发的,这是个误导,不管手动提交还是自动提交MVCC机制都是生效的,只是手动提交用来观察mvcc过程更加直观。

此处为了直观,我们也以手动提交为例,首先通过set  autocommit=0可以关闭自动提交。关闭后每次执行sql以后,通过commit命令来手动提交,才会对数据库产生影响,否则只会对当前操作方的数据快照有影响。innodb引擎中,其他客户端想查看到最新的数据情况也必须通过commit指令来做一次同步(因为innodb默认隔离级别为可重复读)。

当一个会话修改某行数据,未commit前,其他会话对该行数据的修改会阻塞挂起,直到先改那个会话commit为止。

3.4.4.间隙锁

使用范围条件匹配时,innodb会给符合条件的已有数据记录的索引加“范围锁”(范围锁是特殊的行锁),对于键值在条件范围内但并不存在的记录,叫做间隙(GAP),innodb也会对这个间隙加锁,这种机制叫做“间隙锁”。

3.4.5.行锁变表锁 

任何需要全表扫描的情况时,行锁都会升级为表锁。

因为MySQL不知道到底该锁哪行,所以会将整个表都锁起来,然后再进行全表扫描。

全表扫描的情况无非两种:

  1. 没建索引。
  2. 索引失效。

相关文章:

详解MySQL的并发控制

目录 1.概述 2.事务 2.1.什么是事务 2.2.事务的隔离级别 2.2.1.三种数据一致性问题 2.2.2.四种隔离级别 2.3.如何设置隔离级别 3.锁 3.1.锁与事务的关系 3.2.分类 3.3.表锁 3.3.1.概述 3.3.2.读锁 3.3.3.写锁 3.3.4.保护机制 3.4.行锁 3.4.1.概述 3.4.2.什么…...

Android Termux安装MySQL数据库 | 公网安全远程连接【cpolar内网穿透】

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备,尽管最初并非设计为服务器,但是随着技术的进步我们可以将Android配置为生产力工具,变成一个随身…...

SpringBoot的常见配置

SpringBoot基础配置 1. 配置文件格式问题导入1.1 修改服务器端口1.2 自动提示功能消失解决方案1.3 SpringBoot配置文件加载顺序 2. yaml问题导入2.1 yaml语法规则2.2 yaml数组数据2.3 yaml数据读取 3. 多环境开发配置问题导入3.1 多环境启动配置3.2 多环境启动命令格式3.3 多环…...

LabVIEWCompactRIO 开发指南25 实施LabVIEW FPGA代码的方法

LabVIEWCompactRIO 开发指南25 实施LabVIEW FPGA代码的方法 开始开发时,应在LabVIEW项目的FPGA目标下创建VI,以便使用LabVIEW FPGA选板进行编程,该选板是LabVIEW选板的子集,包括一些LabVIEW FPGA特定函数。 应该在仿真模式下开…...

如何利用Jmeter从0到1做一次完整的压测

压测,在很多项目中都有应用,是测试小伙伴必备的一项基本技能,刚好最近接手了一个小游戏的压测任务,一轮压测下来,颇有收获,赶紧记录下来,与大家分享一下,希望大家能少踩坑。 一、压测…...

蓝桥:前端开发笔面必刷题——Day1 数组(一)

文章目录 📋前言🎯数组中重复的数字📚题目内容✅解答 🎯两数之和📚题目内容✅解答 🎯替换空格📚题目内容✅解答 🎯二维数组中的查找📚题目内容✅解答 📝最后 …...

SQL 教程-入门基础篇

文章目录 SQL 简介SQL 语法SQL SELECT 语句SQL SELECT DISTINCT 语句SQL WHERE 子句SQL AND & OR 运算符SQL ORDER BY 关键字SQL INSERT INTO 语句SQL UPDATE 语句SQL DELETE 语句 SQL 简介 SQL(Structured Query Language)是一种用于管理和操作关系…...

循环自相关函数和谱相关密度(六)——信号的循环平稳性(循环自相关函数)原理及推导

在通信、遥测、雷达和声纳系统中,一些人工信号是一类特殊的非平稳信号,它们的非平稳性表现为周期平稳性。通信信号常用待传输信号对周期性信号的某个参数进行调制、如对正弦载波进行调幅、调频和调相,以及对周期性脉冲信号进行脉幅、脉宽和脉位调制,都会产生具有周期平稳性…...

C/C++:04. 多态和虚函数

不加virtual,只能访问成员变量,不能访问成员函数 文章目录 前言1 虚函数与多态不用虚函数的多态使用虚函数的多态 2 C虚函数注意事项 构成多态的条件C虚函数注意事项构成多态的条件什么时候声明虚函数 3 C虚析构函数的必要性总结 前言 本节阐述C中的多态…...

拿下多个定点/比亚迪要上!这项技术要「降维打击」单目感知

2008年,斯巴鲁在全球首次推出了搭载有立体视觉摄像头的主动安全解决方案,并具有紧急制动功能的“EyeSight”。2010年,斯巴鲁推出升级版的“EyeSight”,成为世界上首个可以在全车速范围内避免碰撞的量产技术系统。 2014年&#xff…...

Go 的时间操作

Go 的时间操作 1. time 包 1.1. 时间类型 Go 语言中时间类型有两种: time.Time:表示时间的类型,常见的有两种方式: time.Now():获取当前的时间time.Date():根据指定的年、月、日、时、分、秒、纳秒等创…...

ThreeJS进阶之矩阵变换

ThreeJS的矩阵变换 Three.js使用matrix编码3D变换 —— 平移(位置),旋转和缩放。Object3D的每个实例都有一个matrix,用于存储该对象的位置,旋转和比例。这里介绍如何更新对象的变换。 三维物体(Object3D) 这是Three.js中大部分对象的基类,提供了一系列的属性和方法来对…...

分布式锁概念

什么是分布式锁 方案一:SETNX EXPIRE 方案二:SETNX value值是(系统时间过期时间) 方案三:使用Lua脚本(包含SETNX EXPIRE两条指令) 方案四:SET的扩展命令(SET EX PX NX) 方案五…...

PMP课堂模拟题目及解析(第10期)

91. 在项目执行阶段,一名项目干系人要求项目经理加入一个新过程的优化。项目经理应该怎么做? A. 执行实施整体变更控制过程。 B. 与过程专家一起审查项目。 C. 将优化项目分配给团队。 D. 拒绝范围蔓延企图。 92. 项目经理要求团队提供对项目应急计…...

Arm微架构分析系列3——Arm的X计划

1. 引言 前文介绍了Arm公司近几年在移动处理器市场推出的Cortex-A系列处理器。Cortex-A系列处理器每年迭代,性能和能效不断提升,是一款非常成功的产品。但是,Arm并不满足于Cortex-A系列每年的架构小幅度升级,又推出了X计划&#x…...

Kubernetes(K8S)的基础概念

文章目录 一、Kubernetes介绍1、什么是Kubernetes?2、为什么要用K8S?3、k8s的特性 二、k8s集群架构与组件1、Master组件2、配置存储中心——etcd3、Worker Node 组件 三、k8s核心概念●Pod●Pod 控制器(五大控制器)●Label●Label选择器(Label selector )●Service…...

【Linux进阶命令 04】lsof (看看是谁动了我的文件?)

文章目录 一、简介二、lsof语法2.1 基本格式2.2 选项2.3 输出字段解释 三、常用 lsof 操作3.1 查看某文件的相关进程3.2 网络相关:-i3.3 指定进程号打开的文件:-p3.4 指定用户打开的文件:-u3.5 某进程打开的文件:-c3.6 复合查询 四…...

华为OD机试真题 Java 实现【数字加减游戏】【2023Q1 200分】

一、题目描述 小明在玩一个数字加减游戏,只使用加法或者减法,将一个数字s变成数字t。 每个回合,小明可以用当前的数字加上或减去一个数字。 现在有两种数字可以用来加减,分别为a,其中b没有使用次数限制。 请问小明…...

Python: 结合多进程和 Asyncio 以提高性能

动动发财的小手,点个赞吧! 简介 多亏了 GIL,使用多个线程来执行 CPU 密集型任务从来都不是一种选择。随着多核 CPU 的普及,Python 提供了一种多处理解决方案来执行 CPU 密集型任务。但是直到现在,直接使用多进程相关的…...

只需要两步就能快速接入GPT

缘起 最近一个朋友提出,让我出个关于如何快速接入GPT的教程,今天就给大家安排上。 需要的工具 经过实测,这是迄今为止最便捷的接入方式,而且亲测有效。 首先,第一步你需要下载最新版的微软Edge浏览器,去…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

企业如何增强终端安全?

在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

基于 TAPD 进行项目管理

起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...