开发者学堂课程【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' ;
可看到事务隔离级别为 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 v
ariables like ‘tx_isolation' :
看到隔离级别为 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 默认的事务隔离级别
(2)RDS For MySQL 默认事务的隔离级别
四、演示实例
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’;
看到隔离级别为 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' ;
看到隔离级别变为 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;
//查询到 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;
在原生的 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 读已提交。
隔离级别越低,效率越高,事务未提交就能读取,会出现脏读现象。