MySQL事务的隔离级别验证
2021/8/1 19:39:43
本文主要是介绍MySQL事务的隔离级别验证,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言:
事务是保障数据正确的重要方式,事务具有原子性、一致性、隔离性和持久性四个属性。本篇文章主要说一下基于MySQL事务中的隔离性。MySQL事务的隔离性分四个级别,分别是RU(读未提交)、RC(不可重复读)、RR(可重复读)、Serializable(串行化)。不同的隔离级别,可以避免脏读、不可重复、幻读的发生,具体如下图:
本篇文章将通过Navicat图形化工具来验证MySQL的隔离级别,具体操作请阅读正文:
正文:
0.提前准备:
i. 数据准备:
# 创建数据库 CREATE DATABASE test; # 选择数据库 USE test; # 创建用户表 CREATE TABLE user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) ) ; # 插入数据 INSERT INTO `user` (id,name) VALUES (1,'小周'); INSERT INTO `user` (id,name) VALUES (2,'小张'); INSERT INTO `user` (id,name) VALUES (3,'小王');
ii. 临时修改MySQL隔离级别语句:
set session TRANSACTION ISOLATION level READ UNCOMMITTED ;
iii. 临时手动提交事务语句:
set autocommit = 0;
1. MySQL隔离级别使用RU(读未提交)时,出现脏读验证:
我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。
时间 | 事务窗口一 | 事务窗口一 | 无事务窗口 |
---|---|---|---|
T1 | set autocommit = 0; | set autocommit = 0; | |
T2 | set session TRANSACTION ISOLATION level READ UNCOMMITTED ; | set session TRANSACTION ISOLATION level READ UNCOMMITTED ; | 默认隔离级别 |
T3 | BEGIN ; | BEGIN ; | |
T4 | update user set name ='小周2' where id = 1 ; | ||
T5 | select * from user ; | select * from user ; | select * from user ; |
T6 | ROLLBACK; | ||
T7 | select * from user ; | select * from user ; | |
T8 | COMMIT ; | COMMIT ; |
T5时间内三个窗口同时查询情况如下图。窗口一事务更新的数据没有提交时,就被窗口二事务获取到。如果窗口一事务在之后的时间中发送回滚,窗口二事务则获取了脏数据,即出现了脏读。
窗口一事务在T6时,发生了回滚,T7时间内三个窗口的查询结果如下,三个窗口数据一致了。
2. MySQL隔离级别使用RC(不可重复读)时,解决了脏读,验证存在不可重复读:
我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。
时间 | 事务窗口一 | 事务窗口一 | 无事务窗口 |
---|---|---|---|
T1 | set autocommit = 0; | set autocommit = 0; | |
T2 | set session TRANSACTION ISOLATION level READ COMMITTED ; | set session TRANSACTION ISOLATION level READ COMMITTED ; | 默认隔离级别 |
T3 | BEGIN ; | BEGIN ; | |
T4 | update user set name ='小周2' where id = 1 ; | ||
T5 | select * from user ; | select * from user ; | select * from user ; |
T6 | COMMIT ; | ||
T7 | select * from user ; | select * from t_user ; | |
T8 | COMMIT ; |
T5时间内三个窗口同时查询情况如下图。窗口一事务更新的数据没有提交时,窗口二事务没有获取到窗口一事务未提交的数据,避免了脏读。
窗口一事务在T6时,提交了事务,T7时间内窗口二事务再次读取数据,数据发生了改变,造成了不可重复读。
4.MySQL隔离级别使用RR(不可重复读)时,解决了脏读,解决了不可重复读:
我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。
时间 | 事务窗口一 | 事务窗口一 | 无事务窗口 |
---|---|---|---|
T1 | set autocommit = 0; | set autocommit = 0; | |
T2 | set session TRANSACTION ISOLATION level REPEATABLE READ ; | set session TRANSACTION ISOLATION level REPEATABLE READ ; | 默认隔离级别 |
T3 | BEGIN ; | BEGIN ; | |
T4 | update user set name ='小周2' where id = 1 ; | ||
T5 | select * from user ; | select * from user ; | select * from user ; |
T6 | COMMIT ; | ||
T7 | select * from user ; | select * from t_user ; | |
T8 | COMMIT ; |
T1-T6,步骤不再复述,直接展示T7时间,T7时间内窗口二事务再次读取数据,数据没有改变,避免了不可重复读。
5. MySQL隔离级别使用RR(不可重复读)时,存在幻读:
我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。
时间 | 事务窗口一 | 事务窗口一 | 无事务窗口 |
---|---|---|---|
T1 | set autocommit = 0; | set autocommit = 0; | |
T2 | set session TRANSACTION ISOLATION level REPEATABLE READ ; | set session TRANSACTION ISOLATION level REPEATABLE READ ; | 默认隔离级别 |
T3 | BEGIN ; | BEGIN ; | |
T4 | insert into user VALUES (4,'小韩') ; | ||
T5 | select * from user ; | select * from user ; | select * from user ; |
T6 | COMMIT ; | ||
T7 | select * from user ; | select * from t_user ; | |
T8 | insert into user VALUES (4,'小韩') ; | ||
T9 | COMMIT ; |
窗口二事务在T7时间时,查询数据结果如下:
窗口二事务在T7时间时,没有第四条数据,所有决定在T8时间插入第四条数据,结果不能插入,这出现了幻读。
提示:所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。
不可重复读和幻读的区别是:不可重复读是指读到了已经提交的事务的更改数据(修改或删除),幻读是指读到了其他已经提交事务的新增数据。
防止读到更改数据,需要对操作的数据添加行级锁,防止操作中的数据发生变化;防止读到新增数据,需要添加表级锁,将整张表锁定,防止新增数据。
6. MySQL隔离级别使用Serializable(串行化)时,解决幻读:
我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。
时间 | 事务窗口一 | 事务窗口一 | 无事务窗口 |
---|---|---|---|
T1 | set autocommit = 0; | set autocommit = 0; | |
T2 | set session TRANSACTION ISOLATION level SERIALIZABLE; | set session TRANSACTION ISOLATION level SERIALIZABLE; | 默认隔离级别 |
T3 | BEGIN ; | BEGIN ; | |
T4 | insert into user VALUES (4,'小韩') ; | ||
T5 | select * from user ; | select * from user ; | select * from user ; |
T6 | COMMIT ; | ||
T7 | select * from user ; | select * from t_user ; | |
T8 | insert into user VALUES (4,'小韩') ; | ||
T9 | COMMIT ; |
窗口二事务在T5时间内,会一直在处理中。如果窗口一事务不提交,窗口二事务就会等锁超时,即事务必须串行化执行。
窗口二事务在T7时间时,窗口一事务以及提交,可以执行查询,并且发现有第四条数据,就不会在插入数据,避免了幻读。
这篇关于MySQL事务的隔离级别验证的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-16MySQL资料:新手入门教程
- 2024-11-16MySQL资料:新手入门教程
- 2024-11-15MySQL教程:初学者必备的MySQL数据库入门指南
- 2024-11-15MySQL教程:初学者必看的MySQL入门指南
- 2024-11-04部署MySQL集群项目实战:新手入门教程
- 2024-11-04如何部署MySQL集群资料:新手入门指南
- 2024-11-02MySQL集群项目实战:新手入门指南
- 2024-11-02初学者指南:部署MySQL集群资料
- 2024-11-01部署MySQL集群教程:新手入门指南
- 2024-11-01如何部署MySQL集群:新手入门教程