事务隔离级别复习

最近在复习基础知识这一块,又看到了事务的ACID特性以及隔离级别相关的经典八股文,这八股文都啃到掉牙了,这次就来体验一下完整的事务四大隔离级别,概念的东西就不细嗦了,网上一搜一大把囧,本文旨在手动实践

准备工作

不多BB,直接建一张最随便的表,重点是在体验事务的隔离级别上

create table account
(
	name varchar(50) primary key,
	balance int null
);

插入三条测试数据

insert into account values ('a',0),('b',100),('c',200);

read uncommit(读未提交,会出现脏读)

读未提交,一个事务(A)未提交的修改,可以被其他事务读取到,当事务(A)又回滚了此次修改,其他事务再次读取数据,读取到的数据也会随之变成回滚后的数据,即脏读
下面是一个小测试,读取的金额从100变成0,sql执行顺序已用序号标出

测试用sql

session1

# 1 设置隔离级别为读未提交
set tx_isolation = 'read-uncommitted';
# 2 开启事务
begin;
# 3 将用户a钱加上100
update account set balance = balance+100 where name = 'a';
# 7 将事务回滚,虚晃一枪,妹想到吧
rollback;

session2

# 4 开启另一个session,隔离级别设置为读未提交
set tx_isolation = 'read-uncommitted';
# 5 开启事务
begin;
# 6 因前面步骤3将a的钱加了100,所以读到100
select * from account where name = 'a';
# 8 我又读了下a的钱,发现又变回0了,因为步骤7将事务回滚了
select * from account where name = 'a';
# 9 事务结束
commit;

截图总览

在这里插入图片描述

read commit(读已提交,会出现不可重复读)

当事务A在更新数据,但未提交事务,其他事务读取不到未提交事务的修改内容,但提交了的修改其他事务再次去读取时数据可能就发生变化,变成事务提交后的值了
看下面的例子,不多BB

测试sql

session1

# 1 开启另一个session,隔离级别设置为读已提交
set tx_isolation = 'read-committed';
# 2 开启事务
begin;
# 3 第一次在事务里面读,a账号里面0块钱
select * from account where name = 'a';
# 7 又读了下a的钱,发现还是0块钱,因为隔壁的更新事务未提交
select * from account where name = 'a';
# 9 又读了下a的钱,现在变成100块钱了,因为隔壁已将事务提交,步骤3和9都在一个事务内,读取同一个数据,却出现0和100两个值
select * from account where name = 'a';
# 10 事务结束
commit;

session2

# 4 设置隔离级别为读已提交
set tx_isolation = 'read-committed';
# 5 开启事务
begin;
# 6 将用户a钱加上100
update account set balance = balance+100 where name = 'a';
# 8
commit;

截图总览

在这里插入图片描述

可重复读

一个可重复读事务A开启之后,所有的数据都保存了一个快照,无论其他外部事务怎么更新修改数据,在事务A里面读到的数据都不会出现变动,但是新增和删除的就还是防不住,感知不到
例如下面的例子,事务2插入了d数据,并提交,在事务1里面察觉不到(幻读),并在事务1里面想插入d时发现主键冲突

测试sql

session1

# 1 开启另一个session,隔离级别设置为可重复读
set tx_isolation = 'repeatable-read';
# 2 开启事务
begin;
# 3 第一次在事务里面读,a账号里面0块钱
select * from account where name = 'a';
# 9 又读了下a的钱,发现还是0块钱,隔壁的更新事务已提交,但是我不管
select * from account where name = 'a';
# 10 隔壁事务插入了d,但是我查不到
select * from account where name = 'd';
# 11 试图插入d 报错,因为实际上已经有这条数据了,出现主键冲突
insert into account value ('d',1000);
# 12 事务结束
commit;

session2

# 4 设置隔离级别为可重复读
set tx_isolation = 'repeatable-read';
# 5 开启事务
begin;
# 6 将用户a钱加上100
update account set balance = balance+100 where name = 'a';
# 7 插入一条数据d
insert into account value ('d',1000);
# 8 提交事务
commit;

截图总览

在这里插入图片描述

serializable(串行化)

串行化隔离级别最高,但一个事务A一但对某数据进行了读写操作,其他事务都必须等待事务A提交或回滚事务完才能对其进行操作

测试sql

session1

# 1 开启另一个session,设置隔离级别为串行化
set tx_isolation = 'serializable';
# 2 开启事务
begin;
# 3 在事务里面读
select * from account where name = 'a';
# 8 隔壁事务已经占有了b数据,如果要执行这句,会出现死锁报错,但如果commit隔壁事务会发现2个update都是成功的
#select * from account where name = 'b';
# 9 事务结束
commit;

session2

# 4 设置隔离级别为串行化
set tx_isolation = 'serializable';
# 5 开启事务
begin;
# 6 对b进行加100操作
update account set balance = balance+100 where name = 'b';
# 7 隔壁事务已经占有了a数据,这里会等待隔壁事务结束才能执行
update account set balance = balance+100 where name = 'a';
# 10 事务结束
commit;

截图总览

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值