事务与事务隔离级别-MySQL

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 事务 隔离级别 MySQL

1、 事务

事务是由一系列SQL组成,是数据库的原子操作。事务内的一些列SQL要么全部执行完成,要么全部执行失败,不存在部分执行完成部分执行失败的情况。
MySQL 事务示例:


-- 创建用户余额表
CREATE TABLE `user_balance` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `balance` int NOT NULL COMMENT '余额',
  PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '用户余额';

-- 插入6条记录
INSERT INTO `user_balance` (`balance`) VALUES (1);
INSERT INTO `user_balance` (`balance`) VALUES (1);
INSERT INTO `user_balance` (`balance`) VALUES (1);
INSERT INTO `user_balance` (`balance`) VALUES (1);
INSERT INTO `user_balance` (`balance`) VALUES (1);
INSERT INTO `user_balance` (`balance`) VALUES (1);

-- 创建事务更新
BEGIN;
UPDATE `user_balance` SET `balance`=`balance`+1 where id=1;
UPDATE `user_balance` SET `balance`=`balance`-1 where id=1;
COMMIT;

2、事务特性

事务特性满足ACID四个特性,分别为原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

2.1、 原子性(Atomicity)

原子性要求事务中所有操作要么全部提交成功,要么全部失败回滚。原子即不可再分,所以原子性保证你了事务不能处于半完成状态。

2.2、一致性(Consistency)

一致性要求数据库只能从一个一致性状态转换为另一个一致性状态。
例如:

-- 创建事务更新
BEGIN;
UPDATE `user_balance` SET `balance`=`balance`+1 where id=1;
UPDATE `user_balance` SET `balance`=`balance`-1 where id=1;
COMMIT;

以上SQL更新完id为1的记录后由于一些原因数据库系统或操作系统关闭或崩溃,那么由于事务还没有提交,所以这个事务所做的修改不会保存到数据库中。

2.3、隔离性(Isolation)

隔离性表示一个事务中对数据的修改在提交以前对其他事务是不可见的。

比如,可能有两个线程在执行以下事务,事务1执行完成了balance+1,事务2开始执行SELECT操作,此时事务2 查询到的余额并没有加1

-- 线程1执行事务1
BEGIN;
UPDATE `user_balance` SET `balance`=`balance`+1 where id=1;
UPDATE `user_balance` SET `balance`=`balance`-1 where id=1;
COMMIT;

-- 线程2 执行事务2
BEGIN;
SELECT `balance` FROM `user_balance` WHERE id=1;
-- 其他剩余操作
COMMIT;

但是MySQL中,要根据事务隔离级别来确定是否可见。
比如:MySQL中的读未提交就可以在事务中“见”到未提交事务的修改。

2.4、持久性(Durability)

持久性表示事务一旦提交,那么事务所有对应的修改就会永久保存在数据库中。

3、隔离级别

每种数据库对隔离级别的实现不太一样,同样的,MySQL每种存储引擎对隔离级别的实现不太一样。
我们主要关注四种隔离级别:未提交读、提交读、可重复读和可串行化,下面我们对四种隔离级别分别进行介绍。

MySQL的默认事务隔离级别是“可重复读”。

3.1、隔离级别之前的概念

  1. 脏读(Dirty Read)

脏读是指事务可以读取其他事务未提交的数据。事务A在读取了记录B之后,其他事务修改了记录B但未提交,那么事务A在其他事务更新了记录B之后再次读取记录B会得到其他事务修改后的数据。

  1. 幻读(Phantom Row)

幻读是指一个事务A读取了一次范围的记录之后,其他事务在事务A读取过后又在该范围内插入了新的记录,那么当事务A再次读取相同范围的记录会读取到其他事务插入的新记录。InnoDB解决了幻读问题。

  1. 不可重复读(Nonrepeatable Read)

不可重复读是指一个事务A读取了记录B之后,其他事务在事务A读取过后又更新了记录B,那么当事务A在再次读取记录B时,得到的结果不一致。

3.2、未提交读(READ UNCOMMITED)

从字面意思上理解,未提交读是在事务没有提交时,其他事务就可以读到没有提交事务的修改;修改数据的事务回滚,那么就造成了脏读,从而造成业务问题。
1.png

代码示例:

-- 事务A
set session transaction isolation level read uncommitted;
begin;
select balance from user_balance where id=1;
commit;

-- 事务B
set session transaction isolation level read uncommitted;
begin;
update user_balance set balance=balance+2 where id=1;
commit;

执行结果,事务A在第二次SELECT读到了事务B的更改:
事务A:
2.png

事务B:
3.png

3.3、提交读 (READ COMMITTED)

提交读是事务可以读取到已提交事务的修改。
4.png

代码示例:

-- 事务A
set session transaction isolation level read committed;
begin;
select balance from user_balance where id=1;
commit;

-- 事务B
set session transaction isolation level read committed;
begin;
update user_balance set balance=balance+2 where id=1;
commit;

事务A在第一次查询时得到6
5.png

事务B在第一次查询时也得到6
6.png

此时事务B在执行了更新语句后,事务A查询也得到6。当事务B提交以后,事务A查询得到8。
事务B执行update成功并提交:
7.png

事务A查询得到8:
8.png

3.4、可重复读(REPEATABLE READ)

在同一个事务中,无论读取相同记录多少次,得到的结果都是一样的。
9.png

代码示例:

-- 事务A
set session transaction isolation level repeatable read;
begin;
select balance from user_balance where id=1;
commit;

-- 事务B
set session transaction isolation level repeatable read;
begin;
update user_balance set balance=balance+2 where id=1;
commit;

3.5、可串行化(SERIALIZABLE)

10.png

3.6、隔离级别对比

隔离级别 脏读 不可重复读 幻读 加锁度
未提交读
提交读
可重复读
可串行化

4、总结

  1. MySQL 默认的事务隔离级别为可重复读
  2. InnoDB使用MVVC解决了幻读问题
  3. 理解事务隔离级别在开发中非常重要

5、参考

  1. 高性能MySQL(第三版)
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
6天前
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
13天前
|
SQL 关系型数据库 MySQL
MySQL基础:事务
本文详细介绍了数据库事务的概念及操作,包括事务的定义、开启、提交与回滚。事务作为一组不可分割的操作集合,确保了数据的一致性和完整性。文章还探讨了事务的四大特性(原子性、一致性、隔离性、持久性),并分析了并发事务可能引发的问题及其解决方案,如脏读、不可重复读和幻读。最后,详细讲解了不同事务隔离级别的特点和应用场景。
59 4
MySQL基础:事务
|
20天前
|
API C# 开发框架
WPF与Web服务集成大揭秘:手把手教你调用RESTful API,客户端与服务器端优劣对比全解析!
【8月更文挑战第31天】在现代软件开发中,WPF 和 Web 服务各具特色。WPF 以其出色的界面展示能力受到欢迎,而 Web 服务则凭借跨平台和易维护性在互联网应用中占有一席之地。本文探讨了 WPF 如何通过 HttpClient 类调用 RESTful API,并展示了基于 ASP.NET Core 的 Web 服务如何实现同样的功能。通过对比分析,揭示了两者各自的优缺点:WPF 客户端直接处理数据,减轻服务器负担,但需处理网络异常;Web 服务则能利用服务器端功能如缓存和权限验证,但可能增加服务器负载。希望本文能帮助开发者根据具体需求选择合适的技术方案。
56 0
|
20天前
|
C# Windows 监控
WPF应用跨界成长秘籍:深度揭秘如何与Windows服务完美交互,扩展功能无界限!
【8月更文挑战第31天】WPF(Windows Presentation Foundation)是 .NET 框架下的图形界面技术,具有丰富的界面设计和灵活的客户端功能。在某些场景下,WPF 应用需与 Windows 服务交互以实现后台任务处理、系统监控等功能。本文探讨了两者交互的方法,并通过示例代码展示了如何扩展 WPF 应用的功能。首先介绍了 Windows 服务的基础知识,然后阐述了创建 Windows 服务、设计通信接口及 WPF 客户端调用服务的具体步骤。通过合理的交互设计,WPF 应用可获得更强的后台处理能力和系统级操作权限,提升应用的整体性能。
42 0
|
20天前
|
存储 关系型数据库 MySQL
MySQL 中的事务存储引擎深入解析
【8月更文挑战第31天】
12 0
|
27天前
|
存储 关系型数据库 MySQL
深入MySQL:事务日志redo log详解与实践
【8月更文挑战第24天】在MySQL的InnoDB存储引擎中,为确保事务的持久性和数据一致性,采用了redo log(重做日志)机制。redo log记录了所有数据修改,在系统崩溃后可通过它恢复未完成的事务。它由内存中的redo log buffer和磁盘上的redo log file组成。事务修改先写入buffer,再异步刷新至磁盘,最后提交事务。若系统崩溃,InnoDB通过redo log重放已提交事务并利用undo log回滚未提交事务,确保数据完整。理解redo log工作流程有助于优化数据库性能和确保数据安全。
109 0
|
27天前
|
存储 SQL 关系型数据库
MySQL事务日志奥秘:undo log大揭秘,一文让你彻底解锁!
【8月更文挑战第24天】本文深入探讨了MySQL中undo log的关键作用及其在确保事务原子性和一致性方面的机制。MySQL通过记录事务前的数据状态,在需要时能回滚至初始状态。主要介绍InnoDB存储引擎下的undo log实现,包括undo segment和record的结构,而MyISAM则采用redo log保障持久性而非一致性。通过一个简单的SQL回滚示例,展示了undo log如何在实际操作中发挥作用,帮助读者更好地理解并运用MySQL事务管理功能。
102 0
|
3天前
|
NoSQL 关系型数据库 MySQL
微服务架构下的数据库选择:MySQL、PostgreSQL 还是 NoSQL?
在微服务架构中,数据库的选择至关重要。不同类型的数据库适用于不同的需求和场景。在本文章中,我们将深入探讨传统的关系型数据库(如 MySQL 和 PostgreSQL)与现代 NoSQL 数据库的优劣势,并分析在微服务架构下的最佳实践。
|
5天前
|
存储 SQL 关系型数据库
使用MySQL Workbench进行数据库备份
【9月更文挑战第13天】以下是使用MySQL Workbench进行数据库备份的步骤:启动软件后,通过“Database”菜单中的“管理连接”选项配置并选择要备份的数据库。随后,选择“数据导出”,确认导出的数据库及格式(推荐SQL格式),设置存储路径,点击“开始导出”。完成后,可在指定路径找到备份文件,建议定期备份并存储于安全位置。
65 11
|
24天前
|
弹性计算 关系型数据库 数据库
手把手带你从自建 MySQL 迁移到云数据库,一步就能脱胎换骨
阿里云瑶池数据库来开课啦!自建数据库迁移至云数据库 RDS原来只要一步操作就能搞定!点击阅读原文完成实验就可获得一本日历哦~

热门文章

最新文章