mysql提供四种隔离级别,以下分别对四种隔离级别进行测试,更加直观清晰的了解。具体的隔离级别以及其他相关介绍见https://www.cnblogs.com/eric-fang/p/11052304.html
一、测试环境:
1、mysql 5.5.6、Navicat for mysql。
2、新建表并插入数据
CREATE TABLE `tb_user` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`password` varchar(10) DEFAULT NULL,
`sex` char(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10010 DEFAULT CHARSET=utf8;
INSERT INTO `tb_user`(name,password,sex,age) VALUES ('testname', '111', '2', 27);
1、read uncommitted
-- session01 | -- session02 |
-- 查询 结果:
| |
-- 更新数据 | |
-- 再查询 结果: 虽然session02事务还未提交,但是session01已读取到更新的数据,一旦session02由于某些 原因导致事务回滚,那么session01此时读取到的就是脏数据。如果在对读取到的数据进行相关操作, 就会产生数据不一致问题。 | |
2、read committed
-- session01 | -- session02 |
-- 更新数据 | |
-- 查询 结果: 读取到的还是老数据,age并没有是新的 | |
COMMIT; | |
-- 再查询 结果: 解决了脏读问题,但是,session01,前后两次的相同的查询,结果却不一致。即产生了不可重复读的问题 |
3、repeatable read
-- session01 | -- session02 |
-- 查询 结果: | |
-- 更新数据 UPDATE tb_user set age=31 where id=10010; COMMIT; | |
-- 再查询 SELECT * from tb_user; 结果: 可重复读取。 | |
注意:在sess01中,如果在commit之前再继续执行UPDATE tb_user set age=age-1 where id=10010; 的话,此时age不是用30来计算的,而是session02中更新后的31来计算,保证了数据的一致性。使用了MVCC机制,select操作不会更新版本号,是快照读(历史版本);insert、update和delete会更新版本号,是当前读(当前版本)。 |
4、serializable
串行化执行,会执行悲观锁表,并发度极低,开发工作中基本不会使用。