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中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。

时间事务窗口一事务窗口一无事务窗口
T1set autocommit = 0;set autocommit = 0;           
T2set session TRANSACTION ISOLATION level READ UNCOMMITTED ;set session TRANSACTION ISOLATION level READ UNCOMMITTED ;默认隔离级别
T3BEGIN ;BEGIN ;
T4update user set name ='小周2' where id = 1 ;
T5select * from user ;select * from user ;select * from user ;
T6ROLLBACK;
T7select * from user ;select * from user ;
T8COMMIT ;COMMIT ;

        T5时间内三个窗口同时查询情况如下图。窗口一事务更新的数据没有提交时,就被窗口二事务获取到。如果窗口一事务在之后的时间中发送回滚,窗口二事务则获取了脏数据,即出现了脏读。

 

         窗口一事务在T6时,发生了回滚,T7时间内三个窗口的查询结果如下,三个窗口数据一致了。

 

2. MySQL隔离级别使用RC(不可重复读)时,解决了脏读,验证存在不可重复读:

        我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。

时间事务窗口一事务窗口一无事务窗口
T1set autocommit = 0;set autocommit = 0;           
T2set session TRANSACTION ISOLATION level READ COMMITTED ;set session TRANSACTION ISOLATION level READ COMMITTED ;默认隔离级别
T3BEGIN ;BEGIN ;
T4update user set name ='小周2' where id = 1 ;
T5select * from user ;select * from user ;select * from user ;
T6COMMIT ;
T7select * from user ;select * from t_user ;
T8COMMIT ;

         T5时间内三个窗口同时查询情况如下图。窗口一事务更新的数据没有提交时,窗口二事务没有获取到窗口一事务未提交的数据,避免了脏读。

         窗口一事务在T6时,提交了事务,T7时间内窗口二事务再次读取数据,数据发生了改变,造成了不可重复读。

4.MySQL隔离级别使用RR(不可重复读)时,解决了脏读,解决了不可重复读:

        我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。

时间事务窗口一事务窗口一无事务窗口
T1set autocommit = 0;set autocommit = 0;           
T2set session TRANSACTION ISOLATION level REPEATABLE READ ;set session TRANSACTION ISOLATION level REPEATABLE READ ;默认隔离级别
T3BEGIN ;BEGIN ;
T4update user set name ='小周2' where id = 1 ;
T5select * from user ;select * from user ;select * from user ;
T6COMMIT ;
T7select * from user ;select * from t_user ;
T8COMMIT ;

       T1-T6,步骤不再复述,直接展示T7时间,T7时间内窗口二事务再次读取数据,数据没有改变,避免了不可重复读。

5. MySQL隔离级别使用RR(不可重复读)时,存在幻读:

        我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。

时间事务窗口一事务窗口一无事务窗口
T1set autocommit = 0;set autocommit = 0;           
T2set session TRANSACTION ISOLATION level REPEATABLE READ ;set session TRANSACTION ISOLATION level REPEATABLE READ ;默认隔离级别
T3BEGIN ;BEGIN ;
T4insert into user VALUES (4,'小韩') ;
T5select * from user ;select * from user ;select * from user ;
T6COMMIT ;
T7select * from user ;select * from t_user ;
T8insert into user VALUES (4,'小韩') ;
T9COMMIT ;

        窗口二事务在T7时间时,查询数据结果如下:

         窗口二事务在T7时间时,没有第四条数据,所有决定在T8时间插入第四条数据,结果不能插入,这出现了幻读。

        提示:所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。

        不可重复读和幻读的区别是:不可重复读是指读到了已经提交的事务的更改数据(修改或删除),幻读是指读到了其他已经提交事务的新增数据

       防止读到更改数据,需要对操作的数据添加行级锁,防止操作中的数据发生变化;防止读到新增数据,需要添加表级锁,将整张表锁定,防止新增数据。

6. MySQL隔离级别使用Serializable(串行化)时,解决幻读:

        我们在Navicat中启动三个查询窗口,在不同窗口执行不同的语句,来验证我们的猜想。

时间事务窗口一事务窗口一无事务窗口
T1set autocommit = 0;set autocommit = 0;           
T2set session TRANSACTION ISOLATION level SERIALIZABLE;set session TRANSACTION ISOLATION level SERIALIZABLE;默认隔离级别
T3BEGIN ;BEGIN ;
T4insert into user VALUES (4,'小韩') ;
T5select * from user ;select * from user ;select * from user ;
T6COMMIT ;
T7select * from user ;select * from t_user ;
T8insert into user VALUES (4,'小韩') ;
T9COMMIT ;

     窗口二事务在T5时间内,会一直在处理中。如果窗口一事务不提交,窗口二事务就会等锁超时,即事务必须串行化执行。

         窗口二事务在T7时间时,窗口一事务以及提交,可以执行查询,并且发现有第四条数据,就不会在插入数据,避免了幻读。



这篇关于MySQL事务的隔离级别验证的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程