【MySQL】事务?隔离级别?锁?详解MySQL并发控制机制

目录

1.先理清一下概念

2.锁

2.1.分类

2.2.表锁

2.3.行锁(MVCC)

2.4.间隙锁

2.5.行锁变表锁

2.6.强制锁行


1.先理清一下概念

所谓并发控制指的是在对数据库进行并发操作时如何保证数据的一致性和正确性。在数据库中与并发控制相关的概念有如下几个:

  • 事务

  • 隔离界别

这几个概念大家应该都知道,但是我猜很多人没有把它们串在一起搞明白他们之间的关系,导致这三个概念各是各的,造成记忆负担,最后对整个数据库并发控制的体系也云里雾里的。

锁与事务的关系:

在计算机科学中,做并发控制都是用的“标志位”来实现的,说直白一点就是锁,我们基本上可以说计算机科学中并发控制的底层都是锁的思想。在数据库中也不例外,也是通过锁来实现并发控制的。使用上锁之后,整个数据库的读写都会对外呈现出一些特质,这些特质就是事务(ACID),原子性、一致性、隔离性、持久性。

锁与隔离级别的关系:

当然锁有很多,在数据库中有行锁、表锁、读锁、写锁等等......不同级别的锁,ACID这些特质的强弱不同,这个强弱的级别就是“隔离级别”。

所以综合起来说就是用锁来实现并发控制,对外会呈现出事务(ACID),锁的级别的不同,ACID的强弱也不同,隔离级别对应也不同。

三个东西的关系理清楚后,来回顾一下事务和隔离级别的具体内容。

事务:

事务是为了保证SQL之间不产生脏数据。innodb中默认没有被包裹在事务中的一个单条SQL就是一个事务。事务是一类特征的总称,合起来为ACID:

  • 原子性 (Atomicity):一个事务是一个不可分割的工作单元;事务中的所有操作要么全部成功执行,要么全部不执行。如果事务中的任何部分失败,则整个事务将被回滚到事务开始前的状态。
  • 一致性 (Consistency):在事务开始和结束时,数据库都必须处于一致状态。这意味着事务的执行不会违反任何数据库约束或规则,并且会保持业务逻辑上的一致性。一旦事务完成,它应该使数据库从一个有效状态变为另一个有效状态。
  • 隔离性 (Isolation):并发执行的多个事务之间互不干扰,如同它们是按顺序独立执行一样。这防止了脏读(读取未提交的数据)、不可重复读(在同一事务内多次读取同一数据时结果不同)和幻读(在事务中多次执行相同的查询时,由于其他已提交事务的插入或删除操作导致结果集发生变化)等现象。
  • 持久性 (Durability):当事务成功提交后,其对数据库所做的修改将会永久保存,即使系统发生故障(如崩溃、重启等)也不会丢失这些修改。持久性通常是通过日志记录和恢复机制来保证的。

隔离级别:

事务内具有原子性,但是事务间不具有原子性,并发情况下,多事务间仍然会存在脏数据的问题。

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

隔离级别就是为了保证事务之间不产生脏数据。

2.锁

2.1.分类

按照对数据的操作类型分类,分为:读锁、写锁。

按照对数据操作的粒度分类,分为:行锁、表锁、

表锁:

开销小、加锁快,无死锁,锁的粒度大,发生锁冲突的概率最高,并发度最低。

读锁:

又叫共享锁,针对同一份数据,多个读操作可以同时进行而不互相影响。针对被锁表,所有客户端都可以进行读操作,所有客户端都无法进行写操作,加锁方和其他客户端的区别是,加锁方直接不允许进行写操作,而其他客户端的写操作允许进行,只是会被阻塞挂起。锁解开后,所有挂起的操作线程会去重新争抢资源。

写锁:

又叫排它锁,当前写操作没有完成前,它会阻断其他写锁和读锁。针对被锁表,加锁方可以写,其他客户端不行。其他客户端的写操作会直接失败,读操作会被阻塞挂起,解锁以后,被挂起的线程会重新去争抢资源。

保护机制:

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

MySQL中不同引擎支持不同级别的锁,myIsam支持表锁,innodb支持行锁。

2.2.表锁

表锁,我们当然是要基于使用表锁的存储引擎来聊,也就是基于myIsam引擎。

myIsam引擎中的读写锁是自动加的。

myIsam引擎在解锁后的阻塞队列中进行读写锁调度是写优先,这样一旦阻塞队列中大量都是写操作,那么读操作会很难得到锁,变得很慢,从而造成永久堵塞。

当然除了自动加锁,表锁可以通过指令来加锁。

查看所有锁:

show open tables

解锁:

解铃还须系铃人,只有加锁方能解锁。

unlock  tables

加读锁:

lock table 表名 read

加写锁

lock table 表名 write

2.3.行锁(MVCC)

表锁,我们当然是要基于使用表锁的存储引擎来聊,也就是基于innodb引擎。innodb和myIsam最大的不同有两点,一是支持事务,二是采用了行级锁。innodb下读写都是自动加行锁,这没有什么好说的。但是行锁因为粒度太细了,会影响效率的,innodb没有傻傻的只用了行锁,还给出了行锁的优化方案——MVCC。

MVCC,多版本并发控制,本质上就是使用行锁锁定数据。

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

  • 第一种: 基于锁的并发控制,程序员B开始修改数据时,给这些数据加上锁,程序员A这时再读,就发现读取不了,处于等待情况,只能等B操作完才能读数据,这保证A不会读到一个不一致的数据,但是这个会影响程序的运行效率。
  • 第二种:MVCC,每个用户连接数据库时,看到的都是某一特定时刻的数据库快照,在B的事务没有提交之前,A始终读到的是某一特定时刻的数据库快照,不会读到B事务中的数据修改情况,直到B事务提交,才会读取B的修改内容。

MVCC的使用:

MySQL的MVCC是通过手动提交来实现的,数据库默认开启自动提交,通过set autocommit=0可以关闭自动提交。

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

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

2.4.间隙锁

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

2.5.行锁变表锁

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

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

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

  1. 没建索引。

  2. 索引失效。

2.6.强制锁行

通过 for update 可以在无update操作下,强制锁定一行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/724436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android开发基础有哪些,985研究生入职电网6个月

不好意思久等了 这篇文章让小伙伴们久等了。 一年多以来,关于嵌入式开发学习路线、规划、看什么书等问题,被问得没有一百,也有大几十次了。但是无奈自己对这方面了解有限,所以每次都没法交代,搞得实在不好意思。 但…

python之十进制转化成n进制

思路:除以n得商取模,然后再用商除以n得商取模,依此类推,直到商为0,最后将余数逆序输出即为结果 核心代码 result "" # 结果 while x > 0:a x % n # 余数result result str(a)x x // n # 商prin…

js需要同时发起百条接口请求怎么办?--通过Promise实现分批处理接口请求

如何通过 Promise 实现百条接口请求? 实际项目中遇到需要批量发起上百条接口请求怎么办? 最新案例代码在此!点击看看 前言 不知你项目中有没有遇到过这样的情况,反正我的实际工作项目中真的遇到了这种玩意,一个接口…

SanctuaryAI推出Phoenix: 专为工作而设计的人形通用机器人

文章目录 1. Company2. Main2.1 关于凤凰™ (Phoenix)2.2 关于碳™(Carbon)2.3 商业化部署2.4 关于 Sanctuary Corporation 3. My thoughtsReference彩蛋:将手机变为桌面小机器人 唯一入选《时代》杂志 2023 年最佳发明的通用机器人。 称机器人自主做家务的速度和灵…

7.使用os.Args或flag解析命令行参数

文章目录 一、os.Args二、flag包基本使用 Go语言内置的flag包实现了命令行参数的解析,flag包使得开发命令行工具更为简单。 一、os.Args 如果你只是简单的想要获取命令行参数,可以像下面的代码示例一样使用os.Args来获取命令行参数。 package mainimp…

类的生命周期

一个类完整的生命周期,会经历五个阶段,分别为:加载、连接、初始化、使用、和卸载。其中的连接又分为验证、准备和解析三个步骤。如下图所示 加载(Loading) 简单一句话概括,类的加载阶段就是:找…

PTA天梯赛L1 021-030题目解析

目 录 1.L1-021 重要的话说三遍 2.L1-022 奇偶分家 3.L1-023 输出GPLT 4.L1-024 后天 5.L1-025 正整数AB 6.L1-026 I Love GPLT 7.L1-027 出租 8.L1-028 判断素数 9.L1-029 是不是太胖了 10.L1-030 一帮一 1.L1-021 重要的话说三遍 代码&#xff1a; #include<i…

python实现数据爬虫

一&#xff1a;什么是爬虫 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;经常被称为网页追逐者&#xff09;&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字…

java泛型的高级用法

Java 泛型提供了强大的泛型机制&#xff0c;可以在编译时检查类型安全&#xff0c;并且可以编写通用的代码&#xff0c;使得代码更加灵活和重用。除了基本的泛型用法外&#xff0c;还有一些高级的泛型用法&#xff0c;以下是一些常见的高级泛型用法&#xff1a; 泛型通配符&…

【YOLO v5 v7 v8 v9小目标改进】AFPN 渐进式特征金字塔网络:解决多尺度特征融合中,信息在传递过程丢失

AFPN 渐进式特征金字塔网络&#xff1a;解决多尺度特征融合中&#xff0c;信息在传递过程丢失 提出背景AFPN 多尺度特征金字塔 非邻近层次的直接特征融合 自适应空间融合操作 小目标涨点YOLO v5 魔改YOLO v7 魔改YOLO v8 魔改YOLO v9 魔改 提出背景 论文&#xff1a;https:…

人力资源管理软件大比拼:这篇文章帮你做出明智选择!

本期为您盘点的助力现代企业强力提效的人力资源管理软件有&#xff1a;Zoho People&#xff0c;Workday&#xff0c;BambooHR和Namely。 Zoho People人力资源管理软件 Zoho People是一款全面的云端人力资源管理&#xff08;HRM&#xff09;软件&#xff0c;由Zoho Corporation…

Android开发快速上手,2024年展望Android原生开发的现状

前言 很多次小伙伴问到学习方法&#xff0c;我也很想写这样的一篇文章来跟大家讨论下关于学习方法这件事情。 其实学习方法这个事情&#xff0c;我没啥发言权&#xff0c;因为我自己本身都是没啥方法可言的&#xff0c;就瞎折腾那种&#xff0c;但是大家想看这样的一篇文章&a…

TinyEMU编译与使用

TinyEMU编译与使用 1 介绍2 准备工作3 编译TinyEMU3.1 安装依赖库3.2 编译 4 运行TinyEMU4.1 在线运行4.2 离线运行 5 共享目录5.1 修改root_9p-riscv64.cfg5.2 启动TinyEMU5.3 执行挂载命令 6 TinyEMU命令帮助 1 介绍 原名为riscvemu&#xff0c;于2018-09-23&#xff0c;改为…

mapbox鼠标滑到气泡中不关闭气泡。

贴个群号 WebGIS学习交流群461555818&#xff0c;欢迎大家 效果图 像官网这样的例子&#xff0c;我们并不能鼠标移动到上面的popup内容中&#xff0c;但是有时候是有这样的需求的&#xff0c;比如复制里面的值&#xff0c;或者里面加个按钮&#xff0c;可以点击出现弹窗&…

Vue3:使用setup实现组合式开发

一、情景说明 首先&#xff0c;我们应该知道&#xff0c;Vue3中&#xff0c;可以用Vue2的语法&#xff0c;进行配置式开发。 在这里&#xff0c;我们用Vue3的新语法&#xff0c;实现组合式开发 二、案例 1、组件中使用setup代替Vue2中的data、methods等vc配置项 关键配置&a…

declare 模块声明

示例代码&#xff1a; declare module *.css; declare module *.less; declare module *.png;这些代码行是 TypeScript 的模块声明&#xff0c;用于告诉 TypeScript 编译器如何处理某些类型的模块导入。TypeScript 是一种基于 JavaScript 的静态类型检查语言&#xff0c;它允许…

STM32(19)I2C模块 主机发数据

发送数据&#xff1a; 等待空闲&#xff1a; 发送起始位&#xff1a; 发送地址&#xff1a; 发送数据&#xff1a;

鸿蒙中Text组件的展开和收起效果

前言&#xff1a; DevEco Studio版本&#xff1a;4.0.0.600 效果&#xff1a; 原理分析&#xff1a; 通过效果图我们知道&#xff0c;可以将‘...展开’ 盖在文本内容的的右下角来实现这个效果。那么要实现盖上的效果可以通过层叠布局&#xff08;Stack&#xff09;来实现&am…

基于ceph-deploy部署Ceph 集群

Ceph分布式存储一、存储基础1、单机存储设备1.1 单机存储的问题 2、分布式存储(软件定义的存储SDS)2.1 分布式存储的类型 二、Ceph简介1、Ceph优势2、Ceph架构3、Ceph 核心组件4、OSD 存储后端5、Ceph 数据的存储过程6、Ceph 版本发行生命周期 三、Ceph 集群部署1、 基于 ceph-…

【Vue3】Ref 和 ShallowRef 的区别

目录 什么是 Ref什么是 ShallowRef区别对比示例代码 什么是 Ref Ref 是 Vue 3 中的一个新的基本响应式数据类型&#xff0c;它允许我们包装任意的 JavaScript 值&#xff0c;并且在数据变化时发出通知。Ref 提供了一个 .value 属性来访问其内部的值&#xff0c;同时还提供了一…