MySQL 下事务的四种隔离级别|学习笔记

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: 快速学习 MySQL 下事务的四种隔离级别

开发者学堂课程【MySQL 实操课程MySQL 下事务的四种隔离级别】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/717/detail/12816


MySQL 下事务的四种隔离级别

 

目录:

一、事务的隔离级别

二、MySQL 下事务的四种隔离级别

三、查看事务的隔离级别

四、演示实例

五、回顾

 

一、事务的隔离级别

1、原生 MySQL 和 RDS for MySQL 的默认事务隔离级别不一样。

(1)查看 RDS 的默认事务隔离级别

mysql> show variables like tx_isolation' ;

图片1.png

可看到事务隔离级别为 READ-COMMITTED,读已提交

(2)查看自主安装的 mysql 的默认事务级别

新增一个 cloudshell,编辑:

shell@Alicloud:~S /usr/ local/mysql/bin/mysql -uroot -P

//连接本地的。回车。输入公网ID。

Shell@Alicloud:~$ ssh root@47.112.159.55

再输入密码回车,再输入

[root@iZwz9bize6nk8hug8j0vywZ ~]# /usr/local/mysql/bin/mysql -uroot -P

回车。继续输入:查询原生的 MySQL 事务级别

mysql> show variables like ‘tx_isolation' :

图片2.png

看到隔离级别为 REPEATABLE-READ,可重复读。

两种隔离级别不一样。

2、事务的隔离级别

(1)MySQL InnoDB 存储引擎实现SQL标准的4种隔离级别,用来限定事务内外的哪些改变是可见的,哪些是不可见的;

(2)低级别的隔离级别一般支持更高的并发处理,并拥有更低的系统开销;

事务的隔离级别越低,对并发的支持越好。

 

二、MySQL 下事务的四种隔离级别

1、读未提交 (read uncommited)

在其中一个事务中,可以读取到其他事务未提交的数据变化。这种读取其他会话还未提交的事务,叫做脏读现象。在生产环境中不建议使用。

read uncommited 的隔离级别最低。

如,A客户端开启一个事务,这个事务没有执行 commited,也就是在提交之前,通过另外一个客户端能看到A客户端的数据。这种情况在实际数据库中不被允许。不管是哪种类型的数据库,一般不会采用 read uncommited 隔离级别。

2、读已提交 (read commited)

在其中一个事务中,可以读取到其他事务已经提交的数据变化。这种读取也可以叫做不可重复读,允许幻读现象的发生。

read commited 也是 Oracle 数据库默认的事务隔离级别

说明:A 客户端的事务已经 commited 后,另一个客户端才能读取到 A 客户端的数据。

若 A 客户端的事务发生了变更,另一个客户端在开启事务后,经过多次查询同一个数据表的数据,可能会出现不一致的情况。因为另一个客户端在查询过程中,A客户端的其他事务可能会发生数据提交。这样的情况就是幻读。

RDS for MySQL 默认事务级别也是 read commited。

3、可重复读 (repetable read)

它是 MySQL 默认的事务隔离级别,在其中一个事务中,直到事务结束前,都可以反复读取到该事务刚开始时看到的数据,并一直

不会发生变化,避免了脏读、不可重复读和幻读现象的发生

4、串行 (serializable)

在每个读的数据行 上都需要加表级共享锁,在每次写数据时都要加表级排它锁。这会造成 InnoDB 的并发能力下降,大量的超时和

锁竞争就会发生。

 

三、查看事务的隔离级别

1、MySQL 默认的事务隔离级别为可重复读 (repeatable read)。

2、RDS For MySQL 默认事务的隔离级别为读已提交 (read committed)

3、查询代码:show variables like tx_isolation';

(1)MySQL 默认的事务隔离级别

图片3.png

(2)RDS For MySQL 默认事务的隔离级别

图片4.png

 

四、演示实例

1、读未提交 (read uncommitted)

(1)开启两个 MySQL 连接客户端 session1 和 session2。

(2)分别将其当前 session 事务的隔离界别设置为 read uncomitted。

(3)session1 开启一个事务 ,并插入一条数据 。

(4)session2 执行查询,发现可以查询到 session1 刚插入的数据。

(5)实例。用 RDS 的 MySQL 演示

① 打开一个原生的 cloudshell 和一个 RDS 的 cloudshell。

先在 RDS 的 cloudshell 演示查询当前事务隔离级别

mysql> show variables 1ike ‘tx_isolation’;

图片5.png

看到隔离级别为 read committed。在原生的 cloudshell 中查询也是一样。

② 分别修改两个 cloudshell 事务的隔离级别

mysql>set session transaction isolation level read uncommitted; //代表修改当前 session 作用域的系统变量

Query OK,0 rows affected (0.00 sec)

mysql> show variables like ‘tx_isolation' ;

图片6.png

看到隔离级别变为 read uncommited。

③ 开启事务,插入数据

mysql> use aliyun;

Reading table information for completion of table and colunn names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> select * from user;  

图片7.png

//查询到 user 表有4条数据。然后分别开启两个 cloudshell 的事务。

mysql> begin;

Query OK,0 rows af fected (0.00 sec)

//在 RDS 的 cloudshell 里插入数据 5、sunqi

mysql> insert into user values (5,‘sunqi') ;

Query OK,1 row affected (0.00 sec)

mysql> select * from user;  

图片8.png

在原生的 cloudshell 里查询 user 表,也能查询到数据 5、sunqi。按照在 RDS 的cloudshell 里已经开启一个 begin,则在原生的 cloudshell 里是不能查询到新增数据的。因为原生的 cloudshell 里事务开启是未提交。但这时却能查询到,这就是读未提交 (read uncommited) 隔离级别的脏读现象。

2、读已提交 (read committed)

(1)开启两个 MySQL 连接客户端 session1 和 session2。

(2)分别将其当前 session 事务的隔离界别设置为 read committed

(3)session1 开启一个事务,并插入一条数据。

(4)session2 执行查询,发现不能查询到 session1 刚插入的数据,

直到 session1 事务提交。

(5)演示实例

① 分别回滚两个 cloudshell, 修改事务级别为读已提交

mysql> rol1back;

Query OK, 0 rows affected (0.00 sec)

mysql> set session transaction solation level read commnitted;

Query OK,0 rows affected (0.00 sec)

查询两个 cloudshell 的事务级别都变为 READ-COMMITTED。

② 分别 begin 两个 cloudshell 事务;

③ 然后在RDS的cloudshell里插入数据5、sunqi。

mysql> insert into user values (5,‘sunqi') ;

Query OK,1 row affected (0.00 sec)

mysql> select * from user;  

查询到新增数据 5 sunqi。

到原生的 cloudshell 里查询 user 表,发现只有4条数据,没有新增。不管查询多少次,都查询不到。因为 RDS 的 cloudshell 里的事务未提交,需要手动打开 commit 开启提交后到原生的 cloudshell 里才能查询到新增数据。这就是读已提交。

3、可重复读 (repeatable read)

(1) 开启两个 MySQL 连接客户端 session1 和 session2。

(2) 分别将其当前 session 事务的隔离界别设置为 repeatable read

(3) session1 开启一个事务,并插入-条数据。

(4) session2 在开启事务后,在整个事务提交或回滚前,始终无法查询到 session1提交的数据,即使是 session1 已经提交事务也依然查询不到。由此可见,可重复读就是确保在事务开启后的多次查询始终都是事务开启时的状态数据,直到当前事务提交或回滚。

在前边的示例中,RDS 的 cloudshell 里最开始 begin 事务时,只查询到4条数据。在原生的 cloudshell 里 begin 事务后查询也只能查到4条数据。当 RDS 的 cloudshell 里插入数据5,并且已经 commit 提交,再到原生的 cloudshell 里能查询到数据5。

这就是说。在一个事务开启之后,多次查询同一个表的数据可能会发生变化。这是读已提交。

可重复读是在事务开启后,其他事务也执行新的数据提交,即使执行多次查询,仍然只能看到事务开启时最开始的状态。

① 分别回滚两个 cloudshell, 修改事务级别为可重复读。

mysql> rol1back;

Query OK, 0 rows affected (0.00 sec)

mysql> set session transaction solation level repeatable read;

Query OK,0 rows affected (0.00 sec)

查询两个 cloudshell 的事务级别都变为 REPEATABLE READ。

② 分别 begin 两个 cloudshell 事务;

查询两个 cloudshell 都是4条数据。

③ 在 RDS 的 cloudshell 里插入数据 5 sunqi

RDS 的 cloudshell 里能查询到新增数据5。

在原生的 cloudshell 里查询不到新增数据5。

④ 在 RDS 的 cloudshell 里打开 commit 使事务持久化后,再去原生的cloudshell 里查询 user 表仍旧查询不到新增数据5。无论多少次都查询不到。直到原生的 cloudshell 里的事务 commit 提交或者回滚后,才能查询到新增数据。这就是可重复读。

4、串行化 (serializable)

(1) 开启两个 MySQL 连接客户端 session1 和 session2。

(2) 分别将其当前 session 事务的隔离界别设置为 serializable

(3) session1 开启一 个事务,并插入一条数据

(4) 当 session1 写数据且事务未提交前,session2 在开启事务后,执行 select 操作时会被阻塞,很明显出现了锁表。直到触发了锁表的超时时间。

(5) 演示示例

① 分别删除两个 cloudshell 的数据5

mysql> delete from user where id=5;

Query OK, 1 rows affected (0.00 sec)

查询两个 cloudshell 的数据都只有4条。

② 分别修改两个 cloudshell 的事务级别为 serializable ;

mysql> set session transaction isolation level serializable;

③ 分别 begin 两个 cloudshell 的事务

④ 在 RDS 的 cloudshell 里插入数据5 sunqi 后,在原生的 cloudshell 里查询 user 表就被阻塞了,在 RDS 的 cloudshell 里开启事务后,其他事务则不能进行查询了。在 RDS 的 cloudshell 里实际上是进行锁表的操作,直到进行提交或者回滚操作后,原生的 cloudshell 里查询的表才显示出来。如果 RDS 的 cloudshell 里再begin 一次,同样也会阻塞,因为之前的事务会结束。相当于是读已提交再加上一个串行化。

 

五、回顾

本章主要学习了:

1、事务的管理。包括什么是事务、事务的特性。事务的提交、回滚,和事务的ACID 特性。

2、MySQL 下怎么开启、提交、回滚事务这里用两个方式,一种是使用autocormit 手动设置;另一种是通过开启事务 begin 或 start transaction 命令方式。还有隐式提交事务、隐式回滚事务的比较和举例。

3、删除数据的两个命令 truncate 和 delete 的差异。truncate 不能回滚。delete 可以在事务下进行回滚。

4、四种隔离级别及其对比。

MySQL 默认隔离级别是 repetable read 可重复读。RDS for MySQL 是 read commited 读已提交。

隔离级别越低,效率越高,事务未提交就能读取,会出现脏读现象。

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4天前
|
SQL 存储 关系型数据库
MySQL----事务
MySQL----事务
11 3
|
12天前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
MySQL数据库进阶第六篇(InnoDB引擎架构,事务原理,MVCC)
|
23天前
|
存储 关系型数据库 MySQL
MySql创建带事务操作的存储过程
MySql创建带事务操作的存储过程
|
9天前
|
SQL Oracle 关系型数据库
MySQL学习笔记
MySQL学习笔记
14 0
|
4天前
|
关系型数据库 MySQL
|
12天前
|
关系型数据库 MySQL 数据库
MySQL数据库基础第四篇(多表查询与事务)
MySQL数据库基础第四篇(多表查询与事务)
|
15天前
|
SQL 关系型数据库 MySQL
MySQL数据库——事务操作-begin-commit-rollback
MySQL数据库——事务操作-begin-commit-rollback
12 1
|
16天前
|
存储 SQL 关系型数据库
探讨MySQL事务
探讨MySQL事务
12 1
|
17天前
|
存储 SQL 关系型数据库
MYSQL--(1.存储引擎 *2.事务*)
MYSQL--(1.存储引擎 *2.事务*)
|
23天前
|
SQL 关系型数据库 MySQL
MySQL数据库——基础篇总结(概述、SQL、函数、约束、多表查询、事务)一
MySQL数据库——基础篇总结(概述、SQL、函数、约束、多表查询、事务)一
26 5