Mysql隔离级别

Mysql隔离级别

其实以前对隔离级别的概念不是很清除,但是在学习spring事务的时候就更加迷惑了,所有就准备系统的复习一下mysql隔离级别

环境sql

懒的建表,用的是mybatis-plus的demo 加了一个钱的字段

CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` varchar(30) DEFAULT NULL COMMENT '姓名', `age` int(11) DEFAULT NULL COMMENT '年龄', `money` bigint(20) DEFAULT NULL COMMENT '钱财', `email` varchar(50) DEFAULT NULL COMMENT '邮箱', `is_delete` int(11) DEFAULT 0 COMMENT '是否删除', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4; INSERT INTO `mk_base`.`user` (`id`, `name`, `age`, `money`, `email`, `is_delete`) VALUES (1, 'zhangsan', 18, 100, 'test1@baomidou.com', 0); INSERT INTO `mk_base`.`user` (`id`, `name`, `age`, `money`, `email`, `is_delete`) VALUES (2, 'lisi', 20, 100, 'test2@baomidou.com', 0); INSERT INTO `mk_base`.`user` (`id`, `name`, `age`, `money`, `email`, `is_delete`) VALUES (3, 'Tom', 28, 100, 'test3@baomidou.com', 0); INSERT INTO `mk_base`.`user` (`id`, `name`, `age`, `money`, `email`, `is_delete`) VALUES (4, 'Sandy', 21, 100, 'test4@baomidou.com', 0); INSERT INTO `mk_base`.`user` (`id`, `name`, `age`, `money`, `email`, `is_delete`) VALUES (5, 'Billie', 24, 100, 'test5@baomidou.com', 0);

四种隔离等级

read-uncommitted 读未提交

read-committed 读已提交

repeatable-read 可重复读

serializable 序列化

查看默认的隔离级别

# 查询默认的隔离级别 REPEATABLE-READ 可重复度 SELECT @@global.tx_isolation; # 查看当前绘画的隔离级别 SELECT @@tx_isolation # 修改隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE

Serializable

改一下隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE

我们运行前2句sql,启动一个事务但是不要提交;

START TRANSACTION; UPDATE `user` set money = 99 WHERE `name` = "zhangsan"; # 这里先不执行 COMMIT;

我们在启动一个事务去提交,这里都运行 将张三的钱更改成1块钱

START TRANSACTION; UPDATE `user` set money = 1 WHERE `name` = "zhangsan"; COMMIT;

我们可以看见第二个事务会一直卡住,它会等待第一个事务结束后才会执行

知道我们的事务超时,或者是上一个事务提交了

结论

很明显 最安全但是最慢

repeatable-read 可重复读

改一下隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ

我们启动一个事务去查询张三的钱 不要提交事务

START TRANSACTION; SELECT * FROM `user` WHERE `name` = "zhangsan"; # 这里我们先不要提交 COMMIT;

我们可以看见为100元, 我们用另一个事务将钱改成1000元

START TRANSACTION; UPDATE `user` set money = 1000 WHERE `name` = "zhangsan"; COMMIT;

我们可以看见钱已经被我们改成1000元了,但是在之前没有提交的事务中查询,我们查到的还是100元

直到事务提交后,才能查到最新的值

结论

​ 在同一事务中同一sql查询到的值是相同的

这个隔离级别 会产生幻读的问题

模拟一个业务场景

​ 我们需要查询用户名zhangsan是否存在,如果存在则删除张三,

这个时候我们启动一个事务去查询zhangsan,查询到准备删除,这个时候第二个事务把张三删除了,第二个事务提交了,导致第一个事务删除的时候报错了,这就是幻读.

在模拟一个业务场景

​ 我们需要查询用户名zhangsan是否存在,如果不存在则创建张三,

这个时候我们启动一个事务去查询zhangsan,没查询到准备添加,这个时候第二个事务添加了张三,第二个事务提交了,然后第一事务也提交了,导致目前数据库中就有2个为zhangsan 的用户了,登陆时就会有问题;

但是一般账号都会设置为唯一索引,所以第一个事务就会抛出异常.这就是幻读,

read-committed

改一下隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED

结论

​ 在同一事务中,同样的sql读取的数据不同,可以读取到其他事务已经提交的数据

存在不可重复读,和幻读的问题

read-uncommitted

改一下隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

结论

会读取到其他事务没有提交的数据

会出现 脏读,不可重复读,和幻读


__EOF__

本文作者Immortal-mode
本文链接https://www.cnblogs.com/immortal-mode/p/15784809.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   immortal_mode  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
历史上的今天:
2021-01-10 Json
2021-01-10 SpringMVC
2021-01-10 ssm整合
点击右上角即可分享
微信分享提示