mysql事务隔离级别测试

121 阅读3分钟

事务并发问题

1、脏读

又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。

例如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的就是脏数据。

2、不可重复读

同一个事务中,多次读出的同一数据是不一致的。

例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。

3、幻读
例如:事务T1插入id为3的数据,事务T2,查询不存在id为3的数据,然后t1进行了提交,事务2也执行插入id为3的,但是插入失败了已经存在了,但是查询是没有了,就会造成幻读.
注:三种问题看似不太好理解,脏读侧重的是数据的正确性。不可重复度侧重的于对数据的修改,幻读侧重于数据的新增和删除。

//创建数据库
	create database test;
	//创建表
	CREATE TABLE User (
  id INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(20),
  age INT DEFAULT 0
);
INSERT INTO `User` VALUES (1, 'zhangsan', 23);
INSERT INTO `User` VALUES (2, 'lisi', 20);

//查询默认隔离级别
//5.7以后版本:
select @@transaction_isolation;
//5.7以前老版本:
show variables like 't%_isolation';

//修改隔离级别为读未提交
set global transaction isolation level read uncommitted;

read uncommitted

// session1 开启事务,进行一次次查询,session2,开启事务,执行:

update User set name=‘aaaa’ where id = 1;

然后没有,提交,session1再次查询,发现读到未提交的事务了,id为1的已经修改了,如图:

在这里插入图片描述

read committed

//修改隔离级别为不可重复读
set global transaction isolation level read committed ;

修改之后要断开连接重新开启session:

//查询默认隔离级别
//5.7以后版本:
select @@transaction_isolation;
//5.7以前老版本:
show variables like ‘t%_isolation’;

同上的操作,

// session1 开启事务,进行一次次查询,session2,开启事务,执行update查询:

update User set name=‘aaaa’ where id = 1;

select * from User;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AerR4kV0-1596614952420)(C:\Users\yida\AppData\Roaming\Typora\typora-user-images\1596612023570.png)]

这时候已经解决了读未提交;

然后将session2事务进行提交:

commit;

session继续查询,发现数据修改了,堵到了已经提交的数据:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fF1UopJt-1596614952421)(C:\Users\yida\AppData\Roaming\Typora\typora-user-images\1596612147621.png)]

session在同一个事务中,执行同一个查询确出现不同的结果:就会造成不可重复读;

repeatable read

如上的同样的操作,将事务隔离级别设置为 repeatable read ,解决了不可重复读;

set global transaction isolation level repeatable read;

update User set age=3 where id =1;

跟上面操作一样的,但是会造成,幻读:

就是如果,session1,开启事务,session2开启事务,然后session2插入一个wangwu,session1查询没有id为3的,也插入个wangwu,这时候如果session2提交了事务那么session1会插入失败,如果session2还没提交,session1会等待,session2的提交或者回滚,但是这时候session1是没有查询到的,就会造成幻读:

INSERT INTO User VALUES (3, ‘wangwu’, 20);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2aL592mJ-1596614952422)(C:\Users\yida\AppData\Roaming\Typora\typora-user-images\1596614555077.png)]

serializable

serializable就没什么说的了,是给整个表加锁,只有等另外事务执行完成,才能进行操作:

我在session1中开启事务,执行插入id为3的操作,这时候session2去查询User,会等待session1的事务完成…这种隔离级别基本不会用;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C276Q7yh-1596614952423)(C:\Users\yida\AppData\Roaming\Typora\typora-user-images\1596614919833.png)]

set global transaction isolation level serializable;

//查询默认隔离级别
//5.7以后版本:
select @@transaction_isolation;
//5.7以前老版本:
show variables like ‘t%_isolation’;