mysql脏读,不可重复读,幻读及事务级别的理解(结合代码去理解案例你会焕然大悟)

本文主要是介绍mysql脏读,不可重复读,幻读及事务级别的理解(结合代码去理解案例你会焕然大悟),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文目录

    • 前言
    • 脏读
    • 不可重复读
    • 幻读
    • 三者区别:
    • SQL标准定义了4类隔离级别
      • Read Uncommitted(读取未提交内容)
      • Read Committed(读取提交内容)
      • Repeatable Read(可重读)
      • Serializable(可串行化)
    • 4类隔离级别总结

前言

要从微观的角度去理解事物,不要从宏观的角度去看待事物。脏读,不可重复读,幻读。都是在一个操作下,不要理解成我们进行多次操作看到的结果不一样。要注意看着代码来理解。(刚刚学这个的时候我就理解成了,用户多次操作,看到的结果不一样,数值是没错的只是没更新而已。这是一个误区!!)

脏读

一个事务读到另一个事务,尚未提交的修改,就是脏读。这里所谓的修改,除了Update操作,不要忘了,还包括Insert和Delete操作。脏读的后果:如果后一个事务回滚,那么它所做的修改,统统都会被撤销。前一个事务读到的数据,就是垃圾数据。
脏读是很严重的。
在这里插入图片描述
可以看到在T6的时候转账获取余额是900。T7的时候回滚了数据余额应该是1000。可是转账事务余额是900。存100就变成了900+100=1000。可以看看代码,看着代码结合上图应该好理解点。

 //转账事务public void addCount(){//查余额剩余多少T6Integer money = selectMoneyById(id);/*** money=900;** T7这时取钱那边回滚了。** money=1000才是对的。**可是变量money 还是 900* **///存一百块int add=100;int result = money+add;//900+100=1000(T8}

不可重复读

在同一个事务中,再次读取数据时【就是你的select操作】,所读取的数据,和第1次读取的数据,不一样了。就是不可重复读。

你启动一个事务,并做一个select查询操作。查询到的数据,就有可能,和你第2次,3次…n次,查询到的数据不一样。一般情况下,你只会做一次,select查询,并以这一次的查询数据,作为后续计算的基础。因为允许出现,不可重复读。那么任何时候,查询到的数据,都有可能被其他事务更新,查询的结果将是不确定的。

例子看图
在这里插入图片描述
在T4时转账事务的查出来还有1000块钱。T5时刻取钱事务取了100块,余额应该是900才对。可是转账事务还是按照1000来算。1000+100=1100;
代码解释:

 //转账事务public void addCount(){//查余额剩余多少T4Integer money = selectMoneyById(id);/*** money=1000;** T5这时取走了100。** money=900才是对的。** **///存一百块int add=100;int result = money+add;//1000+100=11000(T7}

幻读

事务1读取指定的where子句所返回的一些行。然后,事务2插入一个新行,这个新行也满足事务1使用的查询where子句。然后事务1再次使用相同的查询读取行,但是现在它看到了事务2刚插入的行。这个行被称为幻象,因为对事务1来说,这一行的出现是不可思议的。
例子:
都知道用户账号是唯一的。每次新增用户就要判断一下账号是否存在。事务一要新增一个账号为:123 的用户。事务二也要增加一个账号:123的用户
有了这个前提我们一起看代码:

 public void addUser(){//事务一要新增一个账号为123的用户//根据账号id去查是否存在123的用户boolean userIsExist = selectUserById("123");/*** 假设现在是没有账号为123用户的。userIsExist=false* * 在这时事务二插入了账号为123的用户* * 可是这里userIsExist的值还是false* * */if(!userIsExist){//不存在123的用户才可以新增//开始新增用户insertUser("123");}}

幻读是针对插入和删除的。

三者区别:

脏读的重点是读另一个事务未提交的数据(假若那个事务RollBack, 则这数据就是无效的):某个事务已更新一份数据, 另一个事务在此时读取了同一份数据, 由于某些原因, 前一个RollBack了操作, 则后一个事务所读取的数据就会是不正确的

不可重复读的重点是修改: 同样的条件, 事务读取过的数据, 再次读取出来发现值不一样了

幻读的重点在于新增或者删除: 同样的条件, 第1次和第2次读出来的记录数不一样
当然, 从总的结果来看, 似乎不可重复读和幻读都表现为两次读取的结果不一致, 但如果你从控制的角度来看, 两者的区别就比较大, 对于不可重复读, 只需要锁住满足条件的记录, 对于幻读, 要锁住满足条件及其相近的记录。

注意:多次操作不一样不是我们去点击,操作多次看到的值不一样。是程序,看到值不一样是针对程序内部来说的,不理解可以看回上面代码去理解。

SQL标准定义了4类隔离级别

4类隔离级别包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

Read Uncommitted(读取未提交内容)

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

Read Committed(读取提交内容)

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

Repeatable Read(可重读)

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable(可串行化)

这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。只要操作产生了锁,就不允许其他事务读取和修改!

4类隔离级别总结

在这里插入图片描述
应该明白 什么状况对什么加什么锁(可以分别思考和测试每个隔离级别下脏读、不可重复读、幻读的出现及不出现原因)

不可重复读错误处理:通常可以用 set tran isolation level repeatable read 来设置隔离级别, 这样事务 A 在两次读取表T中的数据时, 事务B如果企图更改表T中的数据(细节到事务A读取数据)时, 就会被阻塞, 直到事务A提交! 这样就保证了, 事务A两次读取的数据的一致性(就不允许两个事物同时读取,修改一个值,要排队等待一个一个来)

幻读错误处理:如果设置 repeatable read, 虽然可以防止事务B对数据进行修改, 但是事务B却可以向表T中插入新的数据, 如何防止这个问题, 我们可以考虑设置最高的事务隔离级别 set tran isolation level serializable, 于是乎, 事务B就只能乖乖的等待事务A的提交, 才能向表T中插入新的数据, 从而避免了幻读(要避免幻读要把表锁住,性能就会很低,开发中很少这么做)

这篇关于mysql脏读,不可重复读,幻读及事务级别的理解(结合代码去理解案例你会焕然大悟)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/539075

相关文章

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring