MySQL事务隔离级别

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 对于数据库的隔离级别之前一直没有做详细整理,最近项目运行中发现了一个问题,所以抽时间对这块认真研究了下

MySQL事务隔离级别

对于数据库的隔离级别之前一直没有做详细整理,最近项目运行中发现了一个问题,所以抽时间对这块认真研究了下

业务场景:
服务A在处理流程中,会调用外部服务B,然后写入一条数据,服务B执行完成后,会回调服务C的接口更新服务A写入的数据。
问题:
在服务B回调服务C的时候总是找不到服务A写入的数据,在服务C中添加延时重试,问题依然存在,但此时查看数据库,对应的数据是已经存在。

先说原因吧,是因为MySQL的事务默认隔离级别是:可重复读。
在服务A调用服务B后,还没有写入数据到数据库,服务B就已经回调服务C了,服务C此时肯定是找不到对应的数据的,由于MySQL默认隔离级别是可重复读(即在一个事务中,对于同一份数据读取都是一样的),所以即使服务A已经写入了数据,服务C依然读取不到。

解决方案:
在服务C中的查询,不要放到一个事务里面,单独提取一个方法,后面的更新逻辑放到同一个事务中

什么是事务?

数据库事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
比如:某人在商店购买100商品,其中包括两个操作:
1.该人账户减少100元
2.商店账户增加100元
这两个操作要么同时执行成功,要么同时执行失败。

数据库事务的ACID性质

  • Atomic:原子性,将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行;
  • Consistent:一致性,事务完成后,所有数据的状态都是一致的,即该人的账户减少了100,商店的账户必须增加100
  • Isolation:隔离性,比如两个人从同一个账户取款,这两个事务对数据的修改必须相互隔离,具体隔离策略后面具体讲解。
  • Duration:持久性,事务完成后,对数据库数据的修改必须被持久化存储。

数据库的隔离级别

在单个事务中,不需要做隔离,所谓数据库隔离级别是针对在并发事务的情况下,解决导致的一系列问题,这些问题包括:脏读、不可重复读、幻读,具体隔离级别如下图:

隔离级别 脏读 不可重复读 幻读
SERIALIZABLE(串行化) 避免 避免 避免
REPEATABLE READ(可重复读) 避免 避免 允许
READ COMMITED(读已提交) 避免 允许 允许
READ UNCOMMITED(读未提交) 允许 允许 允许

SERIALIZABLE(串行化)

当两个事务同时操作数据库中相同数据时,如果第一个事务已经在访问该数据,第二个事务只能停下来等待,必须等到第一个事务结束后才能恢复运行。因此这两个事务实际上是串行化方式运行。

REPEATABLE READ(可重复读)

一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他事务对已有记录的更新。

READ COMMITTED(读已提交数据)

一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且还能看到其他事务已经提交的对已有记录的更新。

READ UNCOMMITTED(读未提交数据)

一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且还能看到其他事务没有提交的对已有记录的更新。

没有事务隔离级别导致的问题

如果没有数据库的隔离级别,数据库的数据是实时变化的,即每个事务都可以读到其它事务修改后的数据,下面结合实例介绍每个场景的问题。

脏读

定义:读到未提交更新的数据

时间点 事务1 事务2
T1 开始事务 --
T2 -- 开始事务
T3 查询账户余额为1000 --
T4 取出100后金额为900 --
T5 -- 查询账户金额为900(脏读)
T6 撤销事务,余额恢复为1000 --
T7 -- 存入100元后,金额变为1000
T8 -- 提交事务

如上事务1取出金额100后又回滚了,即啥都没做,但事务2存入了100,但最终的金额确还是1000,正确应该是1100。
在T5时间节点出现了脏读,如果数据库配置了隔离级别为SERIALIZABLE、REPEATABLE READ、READ COMMITTED,在事务1没有提交的时候,事务2读取的都是原来的值就不会出现问题。

不可重复读

定义:在同一个数据中,两次读取到的数据不一致,读到了其他数据提交更新的数据

时间点 事务1 事务2
T1 开始事务 --
T2 -- 开始事务
T3 查询账户余额为1000 --
T4 -- 查询账户余额为1000
T5 取出100后金额为900 --
T6 提交事务 --
T7 -- 查询账户余额为900(与T4读取的不一致)

事务2的两次读取到的数据不一致,第二次读取到了事务1提交的数据

幻读

定义:读取到另一个事务已提交插入或删除的数据。

时间点 事务1 事务2
T1 开始事务 --
T2 -- 开始事务
T3 -- 统计一年级1班所有的学生人数为40人
T4 一年级1班新增一名学生 --
T5 提交事务 --
T6 -- 再次统计一年级1班的所有学生人数为41人

事务2第一次统计人数为40人,第二次统计为41人,两次统计的结果不一致,同样如果T4时间节点转走一名学生,也会出现不一致

不可重复读和幻读看起来比较类似,都是一个事务里面读取到两次不同的结果
本质的区别是:不可重复读是由于数据更新导致数据不一致导致,幻读是由于插入或删除了数据导致的。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
22天前
|
SQL 关系型数据库 MySQL
轻松入门MySQL:保障数据完整性,MySQL事务在进销存管理系统中的应用(12)
轻松入门MySQL:保障数据完整性,MySQL事务在进销存管理系统中的应用(12)
|
1月前
|
关系型数据库 MySQL 数据库
MySQL事务(简单明了)
MySQL事务(简单明了)
|
1月前
|
SQL 关系型数据库 MySQL
MySQL索引与事务
MySQL索引与事务
104 0
|
1月前
|
关系型数据库 MySQL 数据库
深入探讨MySQL并发事务的问题及解决方案
深入探讨MySQL并发事务的问题及解决方案
75 0
|
1月前
|
SQL 关系型数据库 MySQL
【MySQL 数据库】4、MySQL 事务学习
【MySQL 数据库】4、MySQL 事务学习
44 0
|
2月前
|
SQL 关系型数据库 MySQL
Mysql事务隔离级别和锁特性
Mysql事务隔离级别和锁特性
|
1天前
|
存储 SQL 关系型数据库
MySQL 事务
MySQL 事务
|
15天前
|
存储 SQL 关系型数据库
【MySQL实战笔记】03.事务隔离:为什么你改了我还看不见?-02
【4月更文挑战第7天】数据库通过视图实现事务隔离,不同隔离级别如读未提交、读已提交、可重复读和串行化采用不同策略。以可重复读为例,MySQL使用多版本并发控制(MVCC),每个事务有其独立的视图。回滚日志在无更早视图时被删除。长事务可能导致大量存储占用,应避免。事务启动可显式用`begin`或设置`autocommit=0`,但后者可能意外开启长事务。建议使用`autocommit=1`并显式管理事务,若需减少交互,可使用`commit work and chain`。
30 5
|
28天前
|
关系型数据库 MySQL 测试技术
面试-MySQL的四种事务隔离级别
面试-MySQL的四种事务隔离级别
18 0
|
29天前
|
存储 缓存 关系型数据库
MySQL事务的四大特性是如何保证的
在MySQL数据库中还有一种二进制日志,其用来基于时间点的还原及主从复制。从表面上来看其和重做日志非常相似,都是记录了对于数据库操作的日志。但是,从本质上来看有着非常大的不同。
14 1