关于msyql事务隔离你要知道

作者:三不猴 时间:2024-01-27 11:07:31 

什么是事务?

事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的:

  1. 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。

  2. 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

隔离性与隔离级别

提到事务,你肯定会想到ACID(Atomicity、Consistency、Isolation、Durability,即原子性、一致性、隔离性、持久性),今 天我们就来说说其中I,也就是“隔离性”。当数据库上有多个事务同时执行的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读 (phantom read)的问题,为了解决这些问题,就有了“隔离级别”的概念。隔离级别做的越强则性能就越不好,所以要在性能与隔离级别中取一个平衡点。SQL标准的事务隔离级别包括:

  • 读未提交(read uncommitted):一个事务提交之后,它做的变更才会被其他事务看到。会产生脏读。

  • 读已提交(read committed):一个事务提交之后,它做的变更才会被其他事务看到。会产生不可重复读。

  • 可重复读(repeatable read) :一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级 别下,未提交变更对其他事务也是不可⻅的。会产生幻读。

  • 串行化(serializable ):顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前 一个事务执行完成,才能继续执行。

隔离级别脏读不可重复读幻读
读未提交可以出现可以出现可以出现
读提交不允许出现可以出现可以出现
可重复读不允许出现不允许出现可以出现
序列化不允许出现不允许出现不允许出现

主要是读已提交和可重复读比较难区分,所以我们看个小例子。先创建一张表,并插入数据1


create database test;
use test;
create table test(id int primary key);
insert into test(id) values(1);

事务A事务B
启动事务查询得到1启动事务

查询得到1

将1改为2
查询得到V1

提交事务B
查询得到V2
提交事务A
查询得到V3

我们来看看在不同的隔离级别下,事务A会有哪些不同的返回结果,也就是图里面V1、V2、V3的返回值分别是什么。

  • 若隔离级别是“读未提交”, 则V1的值就是2。这时候事务B虽然还没有提交,但是结果已经被A看到了。因此,V2、V3也都 是2。

  • 若隔离级别是“读提交”,则V1是1,V2的值是2。事务B的更新在提交后才能被A看到。所以, V3的值也是2。

  • 若隔离级别是“可重复读”,则V1、V2是1,V3是2。之所以V2还是1,遵循的就是这个要求:事务在执行期间看到的数据前 后必须是一致的。

  • 若隔离级别是“串行化”,则在事务B执行“将1改成2”的时候,会被锁住。直到事务A提交后,事务B才可以继续执行。所以从 A的⻆度看, V1、V2值是1,V3的值是2。

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

那什么时候需 要**“可重复读”**的场景呢?

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

事务隔离的实现

在MySQL中,实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,都可以得到前一个状态的值。假设一个值从1被按顺序改成了2、3、4,在回滚日志里面就会有类似下面的记录。

关于msyql事务隔离你要知道

当前值是4,但是在查询这条记录的时候,不同时刻启动的事务会有不同的read-view。如图中看到的,在视图A、B、C里面, 这一个记录的值分别是1、2、4,同一条记录在系统中可以存在多个版本,就是数据库的多版本并发控制(MVCC)。对于 read-view A,要得到1,就必须将当前值依次执行图中所有的回滚操作得到。即使现在有另外一个事务正在将4改成5,这个事务跟read-view A、B、C对应的事务是不会冲突的。

回滚日志总不能一直保留吧,什么时候删除呢?

在不需要的时候才删除。也就是说,系统会判断,当没有事务再需要用到这些回滚日志时,回滚日志会被删除。

什么时候才不需要了呢?

就是当系统里没有比这个回滚日志更早的read-view的时候。

为什么尽量不要使用事务?

事务意味着系统里面会存在很老的事务视图,在这个事务提交之前,回滚记录都要保留, 这会导致大量占用存储空间。除此之外,事务还占用锁资源,可能会拖垮库。

来源:https://juejin.im/post/6854573222491652103

标签:mysql,事务,隔离
0
投稿

猜你喜欢

  • 在django模板中实现超链接配置

    2023-03-03 12:22:44
  • PyQt5实现暗黑风格的计时器

    2023-07-07 02:49:30
  • 如何用C代码给Python写扩展库(Cython)

    2023-06-08 17:06:32
  • python中re.findall函数实例用法

    2021-03-28 07:51:20
  • PHP中Trait及其应用详解

    2023-11-24 06:33:05
  • Django框架之中间件MiddleWare的实现

    2021-03-25 15:08:30
  • Python排序算法之插入排序及其优化方案详解

    2021-04-03 05:39:31
  • 编写安全的SQL Server扩展存储过程

    2008-11-25 11:16:00
  • 对dataframe进行列相加,行相加的实例

    2023-07-24 16:57:59
  • Qt6.5 grpc组件使用 + golang grpc server示例详解

    2024-02-07 21:25:12
  • javascript实现多栏闭合展开式广告位菜单效果实例

    2024-04-29 14:07:44
  • SQLServer2005混合模式登录配置(用户登录错误18452,233,4064)

    2024-01-28 17:47:34
  • 详解python中静态方法staticmethod用法

    2023-08-31 07:56:31
  • mysql复制表的几种常用方式总结

    2024-01-25 12:11:59
  • 详解JavaScript中的Object.is()与"==="运算符总结

    2024-04-22 12:50:25
  • 原生js实现移动小球(碰撞检测)

    2024-04-19 09:56:01
  • 对MySQL几种联合查询的通俗解释

    2024-01-18 17:44:40
  • 听歌识曲--用python实现一个音乐检索器的功能

    2021-11-01 00:46:03
  • Django基于ORM操作数据库的方法详解

    2024-01-28 18:53:52
  • Go语言实现一个简单的并发聊天室的项目实战

    2024-02-15 03:40:33
  • asp之家 网络编程 m.aspxhome.com