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

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

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

测试数据准备

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

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大哥都听到了,但他俩不知道由谁来改,就分别进行了下方流程操作:

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

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

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

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

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

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

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

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

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

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

陈哈哈:???

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

隔离级别概述

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

实例分析

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

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

  • 读未提交(RU)

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

  • 读提交(RC)

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

  • 可重复读(RR)

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

  • 串行(xíng)化(S)

串行化隔离级别不支持并发事务,由于事务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 |+-----------------------+----------------+

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

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

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

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

测试建表语句

-- 建表语句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

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

  1. mysql 什么树_搞懂MySQL InnoDB B+树索引

    一.InnoDB索引 InnoDB支持以下几种索引: B+树索引 全文索引 哈希索引 本文将着重介绍B+树索引.其他两个全文索引和哈希索引只是做简单介绍一笔带过. 哈希索引是自适应的,也就是说这个不能 ...

  2. 一文搞懂MySQL XA如何实现分布式事务

    一文搞懂MySQL XA如何实现分布式事务 前言 XA 协议 如何通过MySQL XA实现分布式事务 前言 MySQL支持单机事务的良好表现毋庸置疑,那么在分布式系统中,涉及多个节点,MySQL又是如 ...

  3. 学习最新大厂付费视频时整理的万字长文+配图带你搞懂 MySQL

    万字长文+配图带你搞懂 MySQL MySQL SQL的介绍 SQL分类 MySQL语法 创建数据库 修改.删除.使用数据库 DDL查询数据表 DDL创建数据表 修改数据表结构 删除数据表 DML添加 ...

  4. 丁奇mysql45讲百度云下载_MySQL实战45讲,丁奇带你搞懂MySQL【完结】

    开篇词.这一次,让我们一起来搞懂MySQL.mp3 开篇词.这一次,让我们一起来搞懂MySQL.pdf 01.基础架构:一条SQL查询语句是如何执行的?.mp3 01.基础架构:一条SQL查询语句是如 ...

  5. 一文搞懂MySQL数据库分库分表

    如果数据量过大,大家一般会分库分表.分库需要注意的内容比较少,但分表需要注意的内容就多了. 工作这几年没遇过数据量特别大的业务,那些过亿的数据,因为索引设置合理,单表性能没有影响,所以实战中一直没用过 ...

  6. 史上最通俗,彻底搞懂字符乱码问题的本质

    1.引言 IM等社交应用的开发工作中,乱码问题也很常见,比如: 1)IM聊天消息中的Emoji表情为什么发给后端后MySQL数据库里会乱码: 2)文件名中带有中文的大文件聊天消息发送后,对方看到的文名 ...

  7. 图文结合带你搞懂MySQL日志之Error Log(错误日志)

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 作者:KAiTO 文章来源:社区原创 往期回顾: 图 ...

  8. mysql decimal型转化为float_5分钟搞懂MySQL数据类型之数值型DECIMAL类型

    速成指南 5分钟搞懂MySQL数据类型 之数值型--DECIMAL类型 DECIMAL类型的语法:DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL].其中M指定的是数字的总位 ...

  9. 一文搞懂 MySQL 索引

    一文搞懂 MySQL 索引 1.MySQL 索引 简介 1.1.MySQL 索引 是什么?  索引是一个单独的.存储在 磁盘 上的 数据库结构 ,包含着对数据表里 所有记录的 引用指针. 1.2. M ...

最新文章

  1. java与ios的区别_好奇?Android与iOS究竟有什么区别?终于知道了!
  2. python中文意思k-对python中的*args与**kwgs的含义与作用详解
  3. 高版本glibc环境编译兼容低版本机器的.so文件
  4. python数据接口设计_Python接口与归一化设计
  5. uCOS-III应用开发笔记之一:uCOS-III在STM32的移植
  6. [转]网友monkeylarry研究生期间我们应该做什么
  7. python3编程环境,使用 python3 环境开发。
  8. html php即时通讯_PHP在线客服即时通讯源码
  9. 超级炫酷个人引导页自适应HTML源码
  10. JSP文件的打开方式
  11. 矩阵特征值和特征向量的求取
  12. Matlab之彩色图像映射表
  13. 下一代CDN如何与智能AI及物联网打通?
  14. Java制作简单小画板
  15. 实践数据湖iceberg 第三十四课 基于数据湖icerberg的流批一体架构-流架构测试
  16. 新知实验室 腾讯云实时音视频产品体验
  17. 思维导图Java篇(一)
  18. Arduino压电震动传感器
  19. Java URL下载图片无法打开问题
  20. 华为鸿蒙OS功能透露,万物互联要来了!华为鸿蒙OS“超级终端”功能曝光

热门文章

  1. java面试题:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
  2. 再也不怕SVN冲突:轻松解决SVN冲突
  3. 测试员不可不知的几款bug管理工具
  4. SpringBoot项目@Email不起作用
  5. ambari 修改服务器名,Ambari修改主页面方法
  6. flume linux 命令,Linux环境Flume安装配置及使用
  7. 6 日期字符串转日期_山西省导游协会关于发放电子导游证的通知 (生成日期为2020年5月28日2020年6月3日)...
  8. android线程优先级大小,android 设置线程优先级 两种方式
  9. oracle创建多个游标,Oracle——游标的创建和使用
  10. linux messages 时间错乱_BATJ 常考的 21 条 Linux 命令,速度收藏!