mysql 默认事务隔离级别_上个厕所的功夫,搞懂MySQL事务隔离级别

“隔离级别” 出于MySQL四大特性(ACID)中的“I”,也就是隔离性。目的是实现数据、事务一致性“C”。

MySQL在多线程并发场景下,可能会出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)这类并发问题,为了解决这些问题,引申出“隔离级别”的概念。

谈隔离级别之前,你首先需要知道,隔离得越严实,效率就会越低。隔离就像是生活中那一件件锁事儿,枷锁越多,活得越累。在很多时候,我们都要在二者之间寻找一个平衡点。

6a820968192f7e2c30c36b160d6f4117.png

测试数据准备

测试表是一些好朋友客串一下,请原谅我的不要脸【/偷笑】。(建表语句在文章末尾)

mysql> select * from department;+----+-----------+-----+-----+------------+------+-----------+| ID | NAME      | SEX | AGE | CLASS      | PAY  | HOBBY     |+----+-----------+-----+-----+------------+------+-----------+|  1 | 陈哈哈    | 男  |  25 | 技术1部    | 3000 | 摸鱼      ||  2 | 扈亚鹏    | 男  |  25 | 技术1部    | 4000 | 美食      ||  3 | 刘晓莉    | 女  |  24 | 技术1部    | 4000 | 摸鱼      ||  5 | 徐立楠    | 女  |  24 | 技术1部    | 4000 | 阅读      ||  6 | 顾昊      | 男  |  25 | 技术1部    | 4000 | 摸鱼      ||  7 | 陈子凝    | 女  |  25 | 技术1部    | 5000 | 看电影    || 14 | 朱志鹏    | 男  |  25 | 技术1部    | 5000 | 看小说    || 19 | 李昂      | 男  |  27 | 技术1部    | 7000 | 看片儿    |+----+-----------+-----+-----+------------+------+-----------+8 rows in set (0.00 sec)

为了更好理解下文,这里先给出个业务场景:

老板:原来陈哈哈是我失散多年的大侄子!财务,给 “陈哈哈” 的工资涨 “10000” 大洋。

陈哈哈:谢谢老叔!MUA~

并发场景下事务存在的数据问题

下面我们介绍一下脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)这三类并发问题,以及每种问题出现的原理及场景。

1. 脏读(针对的是未提交读数据)

事务A修改了数据,但未提交,而事务B查询了事务A修改过却没有提交的数据,这就是脏读,因为事务A可能会回滚。

场景:老板(老叔)大喊了一嗓子,但没有指定哪个财务改。财务A大姐和财务B大哥都听到了,但他俩不知道由谁来改,就分别进行了下方流程操作:

4badb4293bbfd366cc95886ac5142d50.png

就这样,因为 “脏读”就导致我每个月少1万大洋?

2. 不可重复读(针对其他提交前后,读取数据本身的对比)

事务A 先 查询了工资金额,是3000块钱,未提交 。事务B在事务A查询完之后,修改了工资金额,变成了13000, 在事务A前提交了;如果此时事务A再查询一次数据,就会发现钱跟上一次查询不一致,是13000,而不是3000。这就是不可重复读。强调事务A对要操作的数据被别人修改了,但在不知情的情况下拿去做之前的用途。

场景同上:老板嗷一嗓子,但没有指定哪个财务改。财务A大姐和财务B大哥都听到了,但他俩不知道由谁来改,就分别进行了下方流程操作:

bd3990a0003b86d9d042df7821e56c36.png
3d0b81b686875cbefa1ed30ad81f5ad9.png

对于不可重复读,说简单点就是同一个事物内,查到的结果都不一致,就失去了MySQL的“一致性”,这是很严重的错误。你想,如果财务大姐没有二次确认,而是直接以第一次查询为准,又给我加了1万怎么办?想想还有点小激动呢

3. 幻读(针对其他提交前后,读取数据条数的对比)

幻读是指在同一个事务中,存在前后两次查询同一个范围的数据,但是第二次查询却看到了第一次查询没看到的行,一般情况下只新增。

事务A先修改了某个表的所有记录的状态字段为已处理,未提交;事务B也在此时新增了一条未处理的记录,并提交了;事务A随后查询记录,却发现有一条记录是未处理的,很是诧异,刚刚不是全部修改为已处理嘛,以为出现了幻觉,这就是幻读。

场景:老板每个月审批一次涨薪(审批表:shenpiTable),这时财务刚刚把我的工资申请提交了,老板正好在审批。一键审批通过后,突然看到了一条新的“未审批”记录(新增的),还是大侄子陈哈哈的。

老板:有幻觉?有BUG!!等等,我如果假装看不到这月是不是就省了1万块大洋?

陈哈哈:???

4a73c8ed2f362b4ddc0725ef3d4b9b8e.png
  • 脏读说的是事务知道了自己本不应该知道的东西,强调的动作是查询,我看到了自己不该看的东西 ;
  • 不可重复读强调的是一个人查的时候,其他人却可以增删改, 但我却不知道数据被改了,还拿去做了之前的用途;
  • 幻读强调的是我修改了数据,等我要查的时候,却发现有我没有修改的记录,为什么,因为有其他人插了一条新的。

隔离级别概述

为了解决上述问题,MySQL制定了四种不同的“隔离级别”,包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )。

fe6da5c9bd18e60b1eb23de57d1a080c.png

实例分析

(场景再现)老板:原来陈哈哈又双叒(ruò)叕(zhuó)是我失散多年的大侄子!财务,把 “陈哈哈” 的工资涨 “10000” !

以下表中的两个事务为例,看看在不同隔离级别下,分别会出现什么结果。能否避免上述问题呢?

d71432df7c8cc457436f31d9219c54f2.png
  • 读未提交(RU)
669f4800bb044cc36f5e961d4bcea4c0.png

在RU隔离级别下,事务A 在T5时刻,就可以提前读到未提交的事务B 结果。

  • 读提交(RC)
312d789a7722f01fc266ca282382818a.png

读提交又叫读已提交,在RC隔离级别下,事务A 需要在 事务B commit提交后,才能看到事务B 修改的结果。所以在T5时刻,事务A 查到的陈哈哈的工资是 3000。

  • 可重复读(RR)
06612435b222dd36142723abf1738451.png

可重复读是MySQL默认的隔离级别,在RR级别下,对于所有进行中(begin - commit)的事务,比如事务A,无论执行多少次SELECT(查询表 department ),只能看到的是同一张 department 表的结果视图(ReadView),该视图(ReadView)是在本事务启动(begin)时生成的,在事务A 结束(commit)后释放。该隔离级别会保证单事务内查看视图的一致性,称为“可重复读”。

  • 串行(xíng)化(S)
cd4df0f17f552e480036519ee91fbb8c.png

串行化隔离级别不支持并发事务,由于事务A 早于事务B,事务A执行SELECT时,就给 department 表加了锁,事务B 需要等事务A 结束后才能执行,因此T5、T7时刻是 3000,T8时刻事务A提交,事务B释放锁并执行,最后T9时刻查到我的工资是 13000。

原理描述

在实现上,数据库里面会创建一个视图,访问的时候以视图的逻辑结果为准。在MySQL默认的隔离级别“可重复读”隔离级别下,这个视图是在事务启动时创建的,整个事务存在期间都用这个视图。在“读提交”隔离级别下,这个视图是在每个 SQL 语句开始执行的时候创建的。这里需要注意的是,“读未提交”隔离级别下直接返回记录上的最新值,没有视图概念;而“串行化”隔离级别下直接用加锁的方式来避免并行访问。

我们可以看到在不同的隔离级别下,数据库行为是有所不同的。Oracle 数据库的默认隔离级别其实就是“读提交”,因此对于一些从 Oracle 迁移到 MySQL 的应用,为保证数据库隔离级别的一致,你一定要记得将 MySQL 的隔离级别设置为“读提交”。

配置的方式是,将启动参数 transaction-isolation 的值设置成 READ-COMMITTED。你可以用 show variables 来查看当前的值。

mysql> show variables like 'transaction_isolation'; +-----------------------+----------------+| Variable_name | Value |+-----------------------+----------------+| transaction_isolation | READ-COMMITTED |+-----------------------+----------------+

总结来说,存在即合理,每种隔离级别都有自己的使用场景,你要根据自己的业务情况来定。我想你可能会问那什么时候需要“可重复读”的场景呢?我们来看一个数据校对逻辑的案例。

假设你在管理一个个人银行账户表。一个表存了每个月月底的余额,一个表存了账单明细。这时候你要做数据校对,也就是判断上个月的余额和当前余额的差额,是否与本月的账单明细一致。你一定希望在校对过程中,即使有用户发生了一笔新的交易,也不影响你的校对结果。

这时候使用“可重复读”隔离级别就很方便。事务启动时的视图可以认为是静态的,不受其他事务更新的影响。

四种隔离级别的问题解决情况

0b0c892043e4064a2c3a33301e1c07c0.png

测试建表语句

-- 建表语句DROP TABLE IF EXISTS `department`;CREATE TABLE `department` (  `ID` int(11) NOT NULL AUTO_INCREMENT,  `NAME` varchar(30) CHARACTER SET utf8mb4 NOT NULL,  `SEX` char(2) NOT NULL,  `AGE` int(11) NOT NULL,  `CLASS` varchar(10) NOT NULL,  `PAY` int(11) NOT NULL,  `HOBBY` varchar(100) DEFAULT NULL,  PRIMARY KEY (`ID`)) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8;
INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('1', '陈哈哈', '男', '25', '技术1部', '3000', '摸鱼');INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('2', '扈亚鹏', '男', '25', '技术1部', '4000', '美食');INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('3', '刘晓莉', '女', '24', '技术1部', '4000', '摸鱼');INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('5', '徐立楠', '女', '24', '技术1部', '4000', '阅读');INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('6', '顾昊', '男', '25', '技术1部', '4000', '摸鱼');INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('7', '陈子凝', '女', '25', '技术1部', '5000', '看电影');INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('14', '朱志鹏', '男', '25', '技术1部', '5000', '看小说');INSERT INTO `department` (`ID`, `NAME`, `SEX`, `AGE`, `CLASS`, `PAY`, `HOBBY`) VALUES ('19', '李昂', '男', '27', '技术1部', '7000', '看片儿');

总结

以上就是对MySQL中三种并发数据问题以及四种隔离级别的介绍,有些朋友会问,那这几种隔离级别解决上述三种问题的原理是什么呢?可重复读RR是如何解决幻读问题的?

后续解答...

作者:_陈哈哈

原文链接:https://blog.csdn.net/qq_39390545/article/details/107343711

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

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

相关文章

Tg5032smn:高稳定性105℃高温

TG5032SMN是一款频率范围10MHz ~ 54MHz,具有高稳定的TCXO晶振,可与CMOS或限幅正弦输出。外部尺寸5.0 3.2 1.45mm,超小型,质地轻。该系列晶振的额定工作范围-40℃~﹢105C内可高稳定性工作,使得信号频率的误差很小。TG5032SMN与其他…

泰坦尼克号数据集_机器学习入门—泰坦尼克号生存率预测

项目名称:泰坦尼克号生存率预测1.导入数据这里使用kaggle kernel编写代码数据下载地址为:https://www.kaggle.com/c/titanic2.数据统计分析通过describe和info方法,我们可以发现Age,Cabin,Embarked和Fare的数据都有不同…

firefox flash插件_巧用firefox下载视频资源

技术应用场景:1. 免广告播放视频(含vip)2. 下载各大视频网站的视频资源步骤:1.提前下载安装以下程序:火狐浏览器(Firefox)https://www.lanzous.com/i98jfne火狐flash插件 https://www.lanzous.com/i98jercVideo DownloadHelper插件 https://w…

sdr 软件_无线电爱好者系列-1.通过SDR获取周围无线电信号及应用

一、什么是SDR?SDR就是Software Defined Radio,即软件定义无线电。之前的无线电通信系统都是基于特殊的硬件元器件完成无线电信号的接收和解码,例如混频器、滤波器、放大器、调制器和解调器、检波器等。而SDR是基于计算机完成相同的工作,也就是把无线电…

c python 内存冲突_Python在计算内存时应该注意的问题?

我之前的一篇文章,带大家揭晓了 Python 在给内置对象分配内存时的 5 个奇怪而有趣的小秘密。文中使用了sys.getsizeof()来计算内存,但是用这个方法计算时,可能会出现意料不到的问题。 文档中关于这个方法的介绍有两层意思: 该方法…

notepad多行编辑_Windows 10 UWP 推荐 | 极具现代感的轻量化文本编辑器:Notepads

柒才也许你正在用VS Code, Notepad或者Sublime,但是相信很多小伙伴跟我一样,在快速记录笔记或者修改配置文件的时候还是会用Windows系统自带的记事本Notepad.exe(毕竟启动速度快,界面清爽)可是问题在于Windows 10自带的…

python中读取txt文件、统计其中所有字母出现的频度_Python编程小技巧:如何统计序列中元素的出现频度...

原标题:Python编程小技巧:如何统计序列中元素的出现频度实际案例 某随机序列中,找到出现次数最高的三个元素,他们的出现次数是多少? 对某英文文章的单词进行词频统计,找到出现次数最高的10个单词&#xff0…

adsl服务器客户端配置cisco_【干货】Cisco路由排错经典案例分析

关注我,你的眼睛会怀孕对于网工来说,熟悉与掌握路由排错的思路和技巧是非常必要的。接下来,将对三例典型的路由故障排错案例进行分析。一、不堪重负,路由器外网口关闭1、网络环境某单位使用的是Cisco路由器,租用电信30…

centos sudo不能运行_如何在Linux中配置sudo访问权限

Linux 系统中 root 用户拥有 Linux 中全部控制权力。Linux 系统中 root 是拥有最高权力的用户,可以在系统中实施任意的行为。如果其他用户想去实施一些行为,不能为所有人都提供 root 访问权限。因为如果他或她做了一些错误的操作,没有办法去纠…

html文件中文在浏览器中显示乱码问题解决

利用浏览器打开html文件时&#xff0c;中文显示乱码&#xff0c;如下是原文件的内容 1 <html> 2 <head> 3 <title>狗熊王</title> 4 </head> 5 6 <body> 7 <p>狗熊王…

highscore软件_软件|标准物质PDF卡片查找HighScore

有宝物的柜子实用、有趣、干货2019.5.15 前面&#xff0c;我们介绍了Jade软件|MDI Jade 安装包、安装教程、使用手册软件|CasaXPS安装包、安装教程、基本操作&#xff01;今天分享↓↓↓HighScore的安装与简单使用(如有侵权&#xff0c;联系后台删除&#xff01;)第一部分&am…

js图片转二进制流_V8是如何执行一段JS代码的?

汇编器 编译器 解释器解释执行和解释执行什么是V8&#xff1f;V8执行Js代码的过程汇编器 编译器 解释器众所周知&#xff0c;计算机只能理解机器语言&#xff0c;而我们平时编程用的通常是高级语言&#xff0c;所以源代码通常都要经过层层转换最终变成机器语言运行。早期只有汇…

mockito mock void方法_一文让你快速上手 Mockito 单元测试框架

前言在计算机编程中&#xff0c;单元测试是一种软件测试方法&#xff0c;通过该方法可以测试源代码的各个单元功能是否适合使用。为代码编写单元测试有很多好处&#xff0c;包括可以及早的发现代码错误&#xff0c;促进更改&#xff0c;简化集成&#xff0c;方便代码重构以及许…

vs winform常用函数_使用.net core3.0 正式版创建Winform程序

前阵子一直期待.net core3.0正式版本的出来&#xff0c;以为这个版本出来&#xff0c;Winform程序又迎来一次新生了&#xff0c;不过9.23日出来的马上下载更新VS&#xff0c;创建新的.net core Winform项目&#xff0c;发现并没有Winform窗体设计器。而微软目前则是通过插件的方…

VScode中编写运行C/html文件

VScode运行C程序的所需配置 VScode只是一个编辑器&#xff0c;并不自带C编译器&#xff0c;所以需要 下载mingw 下载安装版本或者压缩文件&#xff0c;解压缩后&#xff0c;配置系统的环境变量。 path中添加mingw/bin的路径 新建include变量&#xff0c;添加mingw/include的路径…

linq结果转换object_你知道Object.entries(),但你还知道有Object.fromEntries()吗?

我们得到 object.entries()&#xff0c;它转换一个object → array。但是&#xff0c;如果您想做相反的事情怎么办&#xff1f;不用再想了&#xff01; 使用 Object.fromEntries() 来array → object 。const keyValuePair [ [cow, ], [pig, ],];Object.fromEntries(keyValu…

C语言中数组越界访问造成死循环现象

大家请看这样一段代码&#xff08;工具&#xff1a;VC6.0&#xff09;&#xff1a; #include <stdio.h> int main(int argc, char *argv[]) { int i; int arr[10];/* 这里注意循环变量i与数组arr的定义顺序 */ for(i 0; i < 10; i)/* 这里越界了 */ …

java 同步锁_Java多线程:synchronized同步锁的使用和实现原理

作用和用法在多线程对共享资源进行并发访问方面&#xff0c;JDK提供了synchronized关键字来进行线程同步&#xff0c;实现多线程并发访问的线程安全。synchronized的作用主要体现在三个方面&#xff1a;(1)确保线程互斥地访问同步代码&#xff1b;(2)保证共享变量的线程可见性&…

java基础代码实例_基础篇:详解JAVA对象实例化过程

1 对象的实例化过程对象的实例化过程是分成两部分&#xff1a;类的加载初始化&#xff0c;对象的初始化要创建类的对象实例需要先加载并初始化该类&#xff0c;main方法所在的类需要先加载和初始化类初始化就是执行方法&#xff0c;对象实例化是执行方法一个子类要初始化需要先…

搭建webUI自动化及问题解决:Message: ‘chromedriver‘ executable needs to be in PATH.解决办法

搭建webUI自动化环境 1、conda install selenium即可。 若出现&#xff1a;Message: chromedriver executable needs to be in PATH.Please see https://sites.google.com/a/chromium.org/chromedriver/home。 报错原因&#xff1a;没有配置chrome浏览器的chromedriver 解决…