事务与事务隔离级别-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
目录
相关文章
|
28天前
|
存储 SQL 关系型数据库
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
97 43
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1633 14
|
2月前
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
508 18
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
1月前
|
SQL 关系型数据库 MySQL
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
尼恩,一位40岁的资深架构师,通过其丰富的经验和深厚的技術功底,为众多读者提供了宝贵的面试指导和技术分享。在他的读者交流群中,许多小伙伴获得了来自一线互联网企业的面试机会,并成功应对了诸如事务ACID特性实现、MVCC等相关面试题。尼恩特别整理了这些常见面试题的系统化解答,形成了《MVCC 学习圣经:一次穿透MYSQL MVCC》PDF文档,旨在帮助大家在面试中展示出扎实的技术功底,提高面试成功率。此外,他还编写了《尼恩Java面试宝典》等资料,涵盖了大量面试题和答案,帮助读者全面提升技术面试的表现。这些资料不仅内容详实,而且持续更新,是求职者备战技术面试的宝贵资源。
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
|
1月前
|
存储 关系型数据库 MySQL
RR隔离级别在MySQL中的实现与幻读问题探讨
【10月更文挑战第3天】在数据库管理系统中,事务隔离级别是确保数据一致性和并发性能的关键要素。MySQL作为广泛使用的关系型数据库管理系统,支持多种事务隔离级别,其中可重复读(Repeatable Read,简称RR)是其默认隔离级别。本文将深入探讨RR隔离级别在MySQL中的实现原理,以及RR隔离级别下幻读问题的产生与解决方案。
74 2
|
2月前
|
关系型数据库 MySQL 数据库
深入理解MySQL数据库隔离级别
深入理解MySQL数据库隔离级别
116 1
|
1月前
|
SQL 关系型数据库 MySQL
【MySQL】索引和事务
【MySQL】索引和事务
54 0
|
2月前
|
SQL Oracle 关系型数据库
详解 MySQL 的事务以及隔离级别
详解 MySQL 的事务以及隔离级别
39 0
|
9天前
|
SQL 关系型数据库 MySQL
12 PHP配置数据库MySQL
路老师分享了PHP操作MySQL数据库的方法,包括安装并连接MySQL服务器、选择数据库、执行SQL语句(如插入、更新、删除和查询),以及将结果集返回到数组。通过具体示例代码,详细介绍了每一步的操作流程,帮助读者快速入门PHP与MySQL的交互。
24 1
|
11天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
26 4