欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL的四种事务隔离级别-案例分析

程序员文章站 2024-03-13 20:50:59
...
本文采用的开发环境以及软件如下:
win10,mysql5.7.29,innodb,Toad for MySQL 8.0 Freeware

一、基本概念

MySQL的四种事务隔离级别-案例分析
脏读:事务A和事务B同时打开,对于同一条数据,事务B执行了更新操作(没有提交),事务A能查询到事务B刚更新的数据,此时事务B回退,则事务A查到的就是脏数据。
不可重复读:在事务A多次读取过程中(同一条查询语句),事务B更新数据并提交,导致事务A多次读取到的数据不一致。
幻读:假设此时事务A先查询到4条数据,然后进行更新,在事务A更新前,事务B先插入一条数据并提交,事务A更新后重新查一遍,发现有五条满足条件数据,但是只有4条更新了,就像发生了幻象一样,就是幻读。

小结:对于脏读和不可重复读,主要看是否提交(commit),同一条数据提交前能查到就是脏读,提交后能查到就是不可重复读,比较容易区分。比较难区分的是不可重复读和幻读,不可重复读侧重于数据的修改,幻读侧重于数据的新增与删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表。

二、下面分情况进行讨论

首先要把自动提交关闭
MySQL的四种事务隔离级别-案例分析

2、1 read uncommitted,产生脏读问题

设置数据隔离级别为:read uncommitted
事务A首先查到b=5的数据,
MySQL的四种事务隔离级别-案例分析
事务B执行更新语句,将b=5的数据,a更新为10,但是不执行提交(commit);
MySQL的四种事务隔离级别-案例分析
MySQL的四种事务隔离级别-案例分析
此时事务A执行查询,发现能查到事务B未提交的数据,这就是脏读
说明:read uncommitted级别会造成脏读。
MySQL的四种事务隔离级别-案例分析

2、2 read committed,产生不可重复读问题

首先把事务B回退掉,让数据保持(6,5)。
设置数据隔离级别为:read committed
事务A首先查到b=5的数据,
MySQL的四种事务隔离级别-案例分析
MySQL的四种事务隔离级别-案例分析
事务B执行更新语句,将b=5的数据,a更新为10,但是不执行提交(commit);
MySQL的四种事务隔离级别-案例分析
此时事务A执行查询,发现查不到事务B更新的数据。
MySQL的四种事务隔离级别-案例分析
事务B执行提交操作(commit),事务A再进行查询则可以查到最新数据。
说明:read committed级别解决了脏读
MySQL的四种事务隔离级别-案例分析
虽然read committed解决了脏读,但是还没有解决不可重复读,请往下看。
事务B将b=5更新a=15,并执行commit
MySQL的四种事务隔离级别-案例分析
此时事务A再次进行查询,发现读到了事务B刚刚更新的数据,事务A同一条SQL执行两次,但是两次查询到的结果却不一样,出现不可重复读的问题。
MySQL的四种事务隔离级别-案例分析

2、3 REPEATABLE read,产生幻读问题

设置数据隔离级别为:REPEATABLE read
MySQL的四种事务隔离级别-案例分析
事务A执行查询,此时数据是(15,5)
MySQL的四种事务隔离级别-案例分析
事务B执行更新语句,将b=5更新a=16,并执行提交(commit)操作。
MySQL的四种事务隔离级别-案例分析
此时事务A执行查询,发现还是(15,5)并没有读取到事务B提交的数据,事务A前后两次读取的数据一样。
说明:REPEATABLE read级别解决了不可重复读问题
MySQL的四种事务隔离级别-案例分析
虽然REPEATABLE read级别解决了不可重复读问题,但是还是会产生幻读问题
下面我们改下条件进行查询。查询a >=15的数据,A多次查询还是只有一条(15,5),A想执行更新操作,将a >=1515的数据,b更新成20,但是在更新前,事务B先进行了插入操作。事务B将(16,5)插入到表中并提交。此时在事务B中查询到表中已经有了两条数据。
MySQL的四种事务隔离级别-案例分析
MySQL的四种事务隔离级别-案例分析
事务A执行查询,发现还是(15,5),这是因为当前隔离级别是REPEATABLE read,保证多次读取数据一致。
MySQL的四种事务隔离级别-案例分析
此时A执行更新操作,将a>=15的数据,把b更新成20,提交,然后再查询,发现多出来一条数据,刚刚明明没有a=16的数据,现在出现了,好像发生了幻觉,产生了幻读问题。
MySQL的四种事务隔离级别-案例分析

2、4 SERIALIZABLE,解决幻读问题

设置数据隔离级别为:SERIALIZABLE
MySQL的四种事务隔离级别-案例分析
事务A执行查询
MySQL的四种事务隔离级别-案例分析
事务B执行插入操作,发现插入失败,因为SERIALIZABLE会锁表,因此不会出现幻读的情况,这种隔离级别是最安全的,但是并发性极低,基本上不会用到。
MySQL的四种事务隔离级别-案例分析
MySQL的四种事务隔离级别-案例分析

总结:
1、MySQL数据库默认隔离级别是REPEATABLE read。
2、因为REPEATABLE read(可重复读)的隔离级别下使用了MVCC机制(多版本并发控制),总是读取事务开始时的行数据,所以能都保证每次读取的数据都一致,即select操作不会更新版本号,读的是快照数据,而insert、update和delete会更新版本号,然后再进行select,此时快照已经更新为最新的了,所以会产生幻读问题
3、SERIALIZABLE会进行锁表,所以能都解决幻读问题

相关标签: 数据库