彻底搞懂mysql数据库四种隔离级别,实验实战

数据库四种隔离级别

隔离级别脏读不可重复读幻读
Read uncommitted 读未提交可能可能可能
Read committed 读已提交不可能可能可能
Repeatable read 可重复读不可能不可能可能
Serializable read 串行化不可能不可能不可能

创建一个student表

CREATE TABLE `student` (   `id` int(11) NOT NULL AUTO_INCREMENT,   `class_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,   `class_id` int(11)
NOT NULL,   PRIMARY KEY (`id`),   KEY `idx_class_id` (`class_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ;
INSERT INTO `student`( `class_name`, `class_id`) VALUES ( '初一一班', 1);
INSERT INTO `student`( `class_name`, `class_id`) VALUES ( '初二一班', 2);
INSERT INTO `student`( `class_name`, `class_id`) VALUES ( '初二一班', 3);

一、RU(读未提交)级别下(测试脏读)

事务A事务B
set session transaction isolation level read uncommitted;set session transaction isolation level read uncommitted;
begin;begin;
select * from studentselect * from student
在这里插入图片描述在这里插入图片描述
update student set class_name=‘初一三班’ where class_id=1;
select * from student;select * from student;
在这里插入图片描述在这里插入图片描述
(出现了脏读,读取到了未提交数据)
commit;commit;

结论:和理论一致,出现了出现了脏读,读取到了未提交数据

一、RC(读已提交)级别下(测试脏读、不可重复读)

事务A事务B
set session transaction isolation level read committed;set session transaction isolation level read committed;
begin;begin;
select * from studentselect * from student
在这里插入图片描述在这里插入图片描述
update student set class_name=‘初一三班’ where class_id=1;
select * from student;select * from student;
在这里插入图片描述在这里插入图片描述
(数据没变化)
commit;
select * from student;

(读取到了已提交数据,但是一个事务里俩次读取不一致,出现不可重复读)
commit;

结论:避免了脏读,但是事务B同样的查询,后一次和前一次的结果不一样,这就是不可重读(重新读取产生的结果不一样)。这就很可能带来一些问题,那么我们来看看在RR级别中MySQL的表现。

三、RR(可重复读)级别下(测试不可重复读)

事务A事务B
set session transaction isolation level Repeatable Read;set session transaction isolation level Repeatable Read;
begin;begin;
select * from studentselect * from student
update student set class_name=‘初一三班’ where class_id=1;
select * from student;select * from student;

(数据没变化)
commit;
select * from student;

(数据没变化)
commit;

结论:和理论一致。避免了脏读,和不可重复读

四、RR(可重复读)级别下(测试幻读)

事务A事务B
set session transaction isolation level Repeatable Read;set session transaction isolation level Repeatable Read;
begin;begin;
select * from studentselect * from student
INSERT INTO student(class_name, class_id) VALUES ( ‘初三一班’,4);
commit;
select * from student;
select * from student;

(数据没变化)
commit;

结论:RR 级别下和理论出现不一致。居然避免了幻读

注意: 幻读和不可重复读容易搞混。但不可重复读重点在于update和delete,而幻读的重点在于insert。

在RR级别中,MySQL以乐观锁为理论基础的MVCC(多版本并发控制)来避免这两种问题。通过MVCC机制,虽然让数据变得可重复读,但我们读到的数据可能是历史数据,是不及时的数据,不是数据库当前的数据!这在一些对于数据的时效特别敏感的业务中,就很可能出问题。

数据库的读操作可以分为快照读、当前读。
快照读 select * from XXX
当前读 select * from XXX for update, lock in share mode, update insert delete 等

前面已经介绍了快照读的幻读 在RR级别是不会出现的下面测试当前读是否会有幻读

五、RR(可重复读)级别下(测试[当前读]幻读)

情形1: 针对新增数据的索引id(class_id=1) 与当前读索引id(class_id=1) 相同的幻读测试
事务A事务B
set session transaction isolation level Repeatable Read;set session transaction isolation level Repeatable Read;
begin;begin;
select * from studentselect * from student
update student set class_name=‘初一四班’ where class_id=1;
INSERT INTO student(class_name, class_id) VALUES ( ‘初三一班’,1);
waiting…
select * from student;

修改成功
commit;insert语句执行成功
commit;

情形1:没问题 没有幻读

情形2: 针对新增数据索引id(class_id=30) 大于当前读索引id(class_id=20)的幻读测试
事务A事务B
set session transaction isolation level Repeatable Read;set session transaction isolation level Repeatable Read;
begin;begin;
select * from studentselect * from student
update student set class_name=‘初一四班’ where class_id=20;
INSERT INTO student(class_name, class_id) VALUES ( ‘初三一班’,30);
waiting
commit;insert语句执行成功
commit;

情形2:没问题 没有幻读

情形3: 针对新增数据索引id(class_id=20) 大于当前读索引id(class_id=15)的幻读测试
事务A事务B
set session transaction isolation level Repeatable Read;set session transaction isolation level Repeatable Read;
begin;begin;
select * from studentselect * from student
update student set class_name=‘初一四班’ where class_id=15;
INSERT INTO student(class_name, class_id) VALUES ( ‘初三一班’,20);
insert语句执行成功
update student set class_name=‘初二一班’ where class_id=20;
waiting
commit;
update执行成功
commit;

结论:RR 级别下 当前读也做到了一个事务中查询一致性 避免了幻读

RR级别中,事务A在update后加锁,事务B无法插入新数据,这样事务A在update前后读的数据保持一致,避免了幻读。这个锁,就是Gap锁。

表里带索引的数据classid 为1和20

当当前读修改ID为15锁住了class这部分区间 (1,15]和[15,20)
当当前读修改ID为20锁住了class这部分区间 (1,20]和[20,∞)
当当前读修改ID为30锁住了class这部分区间 [20,30]和[30,∞)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值