模拟四种隔离级别
1.事务的四大特性:
A:原子性:每一个事务都是一个最小单元不可再分
C:一致性:要求在一个事务当中,要么同时成功,要么同时失败,保证数据一致
I:隔离性:一个事务和另一个事务具有一定的隔离性
D:持久性:事务结束的一个保障。事务提交,就相当于把没有保存到硬盘上的数据保存到硬盘上
2.隔离性中的隔离级别
1.读未提交(read uncommitted):最低隔离级别
事务A可以读到事务B未提交的数据
存在问题:存在脏读的问题,我们常称为读到了脏数据。
2.读已提交(read committed):Oracle默认的隔离级别
事务A可以读到事务B已经提交的数据
解决问题:解决了脏读的现象
存在问题:不可重复读取数据。
什么是不可重复读:
在事务开启之后,第一次读到的数据是3条,当事务还没有结束的时候,可能读到4条数据
这样两次读取不同的结果,称为不可重复读(说白了就是两次读取的结果不一样,读取不到相同的数据)
3.可重复读(repeatable read):mysql默认的隔离级别, 读取的都是刚开启事务时的数据
事务A开启之后,每次在事务A中读取的数据都是一致的,即使事务A提交了事务,从事务B读取到的数据还是没有发生改变
解决问题:解决了不可重复读的问题
存在问题:可能会出现幻读的现象:
幻读:读取到的数据是幻象,不够真实
4.可串行化(serializable):最高隔离级别,效率最低
解决了所有的问题
这种隔离级别表示事务排队,不能并发(也就是说一个事务在操作,另一个失误就应该处于等待的状态)
3. 模拟隔离级别
备注:我所写的事务A用来读数据
事务B用来操作数据
模拟读未提交
也就是能读到事务中还没有提交的数据,我们测试一下能不能读到
1.首先我们需要打开两个cmd‘黑窗口’ win+R
一个代表事务A 一个代表事务B
2.设置mysql的隔离级别(在两个黑窗口中任意一个都可以)
命令:set global transaction isolation level READ UNCOMMITTED;
3.首先exit退出之后从新登录mysql然后查看mysql的全局隔离级别有没有设置成功。
命令:select @@tx_isolation;
如果使用这个报错,那就试一下这个↓
select @@transaction_isolation;
4.设置好隔离级别之后,进入一个数据库(use 数据库名) 我们创建一个user表,以这个表为例: 我把创建表语句以及添加数据都已经写好,大家可以复制
drop table if exists user;
create table user(
user_id bigint(20) primary key auto_increment,
user_name varchar(255),
password varchar(255)
);
insert into user (user_name,password) values ('xiaowang','xiaowang123');
insert into user (user_name,password) values ('xiaoliu','xiaoliu123');
insert into user (user_name,password) values ('xiaoli','xiaoli123');
insert into user (user_name,password) values ('xiaohei','xiaohei123');
insert into user (user_name,password) values ('xiaobai','xiaobai123');
5.创建好之后我们查看一下这个表中的内容,我们就以这个为例:
6.两个黑窗口都关闭事务自动提交机制:
命令:start transaction;
7.我们在事务B中做一个删除的操作(不提交事务)
delete from user where user_id = 5;
8.在事务A中进行查询 只查到的四条数据
结果我们发现,我们在事务B中并没有提交事务,但是在事务A中查询的时候却只有四条记录,这是为什那???
这就存在脏读的问题,也就是我们说的读到了脏数据。
读未提交:只要一个事务进行了DML操作,不管有没有提交事务,在另一个事务中可以读到还未提交的事务。
模拟读已提交
读已提交,按照我们的理解就是一个事务读取到另一个事务提交的数据
1.把隔离级别修改为读已提交
set global transaction isolation level READ COMMITTED;
2.使用exit命令退出后从新登录查看,是不是修改成功
命令:select @@tx_isolation;
如果使用这个报错,那就试一下这个↓
select @@transaction_isolation;
3.设置成功之后还是用我们刚才那张表,先进入到指定的数据库
use 数据库名
4.两个黑窗口都关闭自动提交事务机制
命令:start transaction;
5.事务A中查看user数据,我们发现是4条记录
6.然后在事务B中删除一条记录
7.然后在事务A中在查看一下 结果还是四条记录
8.现在我们在事务B中把事务提交 commit
9.然后再从事务A中查看 发现这次就三条记录了
总结:读已提交,事务A 只能读取到事务B 已经提交的事务,这就解决了脏读的问题,读到的数据都是真真实实存在的
但是存在不可重复读的问题 这次查询的数据,和上次查询的数据可能不一样(说白了就是几次查询的结果可能不一样了,不可重复度)
模拟可重复度:
1.还是打开两个黑窗口,登陆上mysql
2.设置隔离级别:set global transaction isolation level repeatable read;
然后exit退出查看一下设置的隔离级别
命令:select @@tx_isolation;
如果使用这个报错,那就试一下这个↓
select @@transaction_isolation;
3.进入到指定的数据库 use 数据库名
4.两个黑窗口都关闭自动提交事务
5.然后在事务A中查看user表 我们发现有两条数据
6.然后在事务B中添加上几条数据 我们在事务B中添加了四条记录,并提交了事务
7.然后我们在事务A中在查看一下,看看会不会多记录 结果发现,还是开启事务时候的那几条记录,并没有改变
总结:
可重复读,当我们开启事务的那一刻,数据就不会发生改变,解决了不可重复读的问题
这样可以做到可以重复的读取相同的的数据,直到这个事务结束了,才可以读到新的记录
但是存在幻读的问题 : 读到的数据是一个幻觉的数据,可能不是真是存在的数据
可串行化
可串行化就不进行模拟了,这个是最高的隔离级别。可以解决以上的所有问题
开启事务之后,只有一个事务执行结束,另一个事务才可以操作 事务是排队执行的
大家在看隔离级别理论的时候可能会看的云里雾里,但是实际的操作一遍就会理解的多,值得尝试一下