MySQL事务隔离级别浅析(2)

所谓脏读就是说,两个事务,其中一个事务能读取到另一个事务未提交的数据。
场景:session1要转出200元,session2转入100元。基数为1000。顺利完成正确的结果应该是900元。但是我们假设session2转入因为某种原因事务回滚。这时正确的结果应该是800元。

演示步骤:
① 新建两个session(会话,在navicat中表现为两个查询窗口,在mysql命令行中也是两个窗口),分别执行

select @@tx_isolation;//查询当前事务隔离级别 2 set session transaction isolation level read uncommitted;//将事务隔离级别设置为 读未提交

② 两个session都开启事务

start transaction;//开启事务

③ session1和session2:证明两个操作执行前账户余额为1000

select * from tb_bank where id=1;//查询结果为1000

④ session2:此时假设session2的更新先执行。

update tb_bank set account = account + 100 where id=1;

⑤ session1:在session2 commit之前session1开始执行。

select * from tb_bank where id=1;//查询结果:1100

⑥ session2:因为某种原因,转入失败,事务回滚。

rollback;//事务回滚 2 commit;//提交事务

⑦  这时session1开始转出,并且session1觉得⑤中查询结果1100就是正确的数据。

update tb_bank set account=1100-200 where id=1; 2 commit;

⑧ session1 和 session2查询结果

select * from tb_bank where id=1;//查询结果:900

这时我们发现因为session1的脏读造成了最终数据不一致。正确的结果应该为800;
到此我们怎么避免脏读呢,将事务的隔离性增加一个级别到read-commit

(2)read-commit解决脏读

重置数据,使数��恢复到account=1000

① 新建两个session,分别设置

set session transaction isolation level read committed;//将隔离级别设置为 不可重复读

重复执行(1)中的②③④步

⑤ session1执行查询

select * from tb_bank where id=1;//查询结果为1000,这说明 不可重复读 隔离级别有效的隔离了两个会话的事务。

这时我们发现,将事务的隔离升级为read-committed;后有效的隔离了两个事务,使得session1中的事务无法查询到session2中事务对数据的改动。有效的避免了脏读。

 2、通过sql演示-----read-committed的不可重复读 (1)read-commit的不可重复读

重置数据,使数据恢复到account=1000

所谓的不可重复读就是说,一个事务不能读取到另一个未提交的事务的数据,但是可以读取到提交后的数据。这个时候就造成了两次读取的结果不一致了。所以说是不可重复读。
READ COMMITTED 隔离级别下,每次读取都会重新生成一个快照,所以每次快照都是最新的,也因此事务中每次SELECT也可以看到其它已commit事务所作的更改
场景:session1进行账户的查询,session2进行账户的转入100。
session1开启事务准备对账户进行查询然后更新,这时session2也对该账户开启了事务进行更新。正确的结果应该是在session1开启事务以后查询读到的结果应该是一样的。

① 新建两个session,分别设置

set session transaction isolation level read committed;

② session1和session2分别开启事务

start transaction;

③ session1第一次查询:

select * from tb_bank where id=1;//查询结果:1000

④ session2进行更新:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9931c84673d1ee9b8844796572552e03.html