您的当前位置:首页 >系统运维 >怎样选择MySQL事务隔离级别? 正文
时间:2025-11-05 05:02:10 来源:网络整理编辑:系统运维
我们回到一个经常会讨论的问题:MySQL事务隔离级别究竟应该怎么选择?先说一下我自己的见解:建议在RC和RR两个隔离级别中选一种,如果能接受幻读,需要并发高点,就可以配置成RC:如果不能接受幻读的情况
我们回到一个经常会讨论的样选问题:MySQL事务隔离级别究竟应该怎么选择?
先说一下我自己的见解:

建议在RC和RR两个隔离级别中选一种,如果能接受幻读,事务需要并发高点,隔离就可以配置成RC:
如果不能接受幻读的样选情况,就设置成RR隔离级别。事务
我们就来详细介绍一下MySQL的隔离4种事务隔离级别。
四种隔离级别的样选基本定义(如果觉得文字不太好理解,可以结合文章后面的事务实验部分):
事务隔离级别
解释
Read uncommitted
(读未提交,简称:RU)
所有事务都可以看到其它未提交事务的隔离执行结果,这也就是样选脏读。
Read Committed
(读已提交,事务简称:RC)
一个事务只能看见已经提交事务所做的隔离改变,某个事务执行期间可能有其他事务提交,样选所以可能出现幻读
Repeatable Read
(可重复读,事务简称:RR)
这是隔离MySQL的默认事务隔离级别,它确保同一事务相同的语句多次查询时,会看到同样的数据行。消除了脏读、不可重复读,默认也不会出现幻读
Serializable
(串行)
这是最高的源码库隔离级别,它通过强制事务排序,使不同事务之间不可能相互冲突,从而解决幻读问题
解释一下幻读:在一个事务里面,按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足查询条件的新数据。这种情况就称为幻读。
创建测试表和写入测试数据:
复制use martin; drop procedure if exists insert_t21; delimiter ;; create procedure insert_t21() begin drop table if exists t21; CREATE TABLE `t21` ( `id` int NOT NULL AUTO_INCREMENT, `a` int NOT NULL, `b` int NOT NULL, PRIMARY KEY (`id`), KEY `idx_c` (`a`) ) ENGINE=InnoDB CHARSET=utf8mb4; insert into t21(a,b) values (1,1),(2,2); end;; delimiter ;1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.按下图进行RU隔离级别的实验:
步骤
session1
session2
1
call insert_t21();
2
set session transaction_isolation=READ-UNCOMMITTED;
set session transaction_isolation=READ-UNCOMMITTED;
3
begin;
begin;
4
select * from t21 where a=1;
5
insert into t21(a,b) values (1,3);
6
select * from t21 where a=1;
7
commit;
commit;
上面的实验中,第 5 步中 session2 写入了一条 a、b 值分别为 1、3 的记录,在第 6 步中,session2 中的事务还没提交,但是 session1 就能看到 session2 写入的数据,出现了脏读现象。
按下图,进行RC隔离级别的实验:
ID
session1
session2
1
call insert_t21 ();
2
set session transaction_isolation=READ-COMMITTED;
set session transaction_isolation=READ-COMMITTED;
3
begin;
begin;
4
select * from t21 where a=1;
5
insert into t21(a,b) values (1,3);
6
select * from t21 where a=1;
7
commit;
8
select * from t21 where a=1;
9
commit;
实验结果是:
session2 写入了新数据未提交的情况下,session1 无法查看到新记录,等到 session2 提交之后,session1 才能看到第 5 步 session2 写入的数据。服务器租用
但是存在一个问题就是在session1这个事务里面,按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据。也就是出现了幻读。
再来看下RR隔离级别下的实验:
ID
session1
session2
1
call insert_t21 ();
2
set session transaction_isolation=REPEATABLE-READ;
set session transaction_isolation=REPEATABLE-READ;
3
begin;
begin;
4
select * from t21 where a=1;
5
insert into t21(a,b) values (1,3);
6
select * from t21 where a=1;
7
commit;
8
select * from t21 where a=1;
9
commit;
10
select * from t21 where a=1;
实验结论:
session2 写入了新数据未提交的情况下,session1 无法查看到新记录,等到 session2 提交但是 session1 还未提交时,session1 还是不能看到新记录,需要等 session1 事务提交之后,才能查看到第 5 步 session2 写入的新数据。
也就是RR隔离级别下,在同一个事务里面,前后两条一样的语句,读取的数据是一样的。
进行如下实验:
ID
session1
session2
1
call insert_t21 ();
2
set session transaction_isolation=SERIALIZABLE;
set session transaction_isolation=SERIALIZABLE;
3
begin;
begin;
4
select * from t21 where a=1;
5
insert into t21(a,b) values (1,3);
(等待)
6
select * from t21 where a=1;
7
commit;
session1 提交后,第 5 步中的写入操作执行成功
8
commit;
9
select * from t21 where a=1;
当 session1 中有事务查询 a=1 这行记录时,WordPress模板在 session2 就不能插入 a=1 的记录,进入等待。必须等 session1 提交后,session2 才能执行成功。也就是让事务串行进行。
拿零售业务场景来讲,在事务隔离级别 RU 下:
比如顾客 A 在超市买单时,
当收银员扫完顾客 A 的支付码后,因为网络原因,一直等待着(也就是整个支付过程的事务还没结束);
这时收银员去后台数据查询,看到 A 的钱已经进入超市账户了,然后让顾客 A 离开。
过了一会,整个支付过程回滚了,才发现 A 实际是支付失败。
这样超市岂不是很亏。
这就是 RU 隔离级别可能导致脏读的情况。
顾客A在超市购买了90元的东西。
收银系统查询到顾客A还剩100元,足够扣款,
A 的老婆在家网购,花掉了A账户里的这100块,
收银系统在扣除A账户90元时,就会出现报错,
顾客A肯定郁闷,不是明明钱够么?
这就是 RC 隔离级别下的幻读现象。
顾客A在超市购买了90元的东西。
当收银系统查询到顾客A还剩100 元,足够扣款,
这期间A 的老婆在家网购,能查询到 A 的账户里还有 100 元,但是想要用 A 账户里的 100 块,却发现并不能使用这 100 元,
A最后的扣款步骤也能正常完成,最终顺利完成了整个付款过程,
这就是可重复读的现象。
顾客A在超市购买了90元的东西。
当收银系统查询到顾客A还剩100元,足够扣款,
此时A 的老婆在家网购,想查询 A 账户里还有多少钱,却发现无法查看到,必须要等到 A 整个付款完成,其老婆才能去查询余额,
这就是串行导致的。
对于RU隔离级别,会导致脏读,从性能上看,也不会比其它隔离级别好太多,因此生产环境不建议使用。
对于RC隔离级别,相比RU隔离级别,不会出现脏读;但是会出现幻读,一个事务中的两次执行同样的查询,可能得到不一样的结果。
对于 RR 隔离级别,相比RC隔离级别,解决了部分幻读,我们在锁那一章也有详细讲解,但是相对于RC,锁的范围可能更大了。
对于 Serializable 隔离级别,因为它强制事务串行执行,会在读取的每一行数据上都加锁,因此可能会导致大量的超时和锁争用的问题。生成环境也不建议使用。
因此总的来说,建议在RC和RR两个隔离级别中选一种,如果能接受幻读,需要并发高点,就可以配置成RC,如果不能接受幻读的情况,就设置成RR隔离级别。
电脑管家帮助你解决登陆错误问题(一键重启功能让你摆脱麻烦)2025-11-05 04:53
浅谈如何将NoSQL引入现有架构系统2025-11-05 04:43
用户视角下的数据安全需求、挑战与演进2025-11-05 04:20
攻击者伪造WhatsApp语音通知来窃取信息2025-11-05 03:40
掌握平板电脑4指操作技巧,高效利用设备(简单易学的平板电脑4指操作教程,助您成为高手)2025-11-05 03:11
Oracle认证:详解OracleTemp临时表空间处理方法2025-11-05 02:52
微软、苹果和谷歌将支持FIDO无密码登录2025-11-05 02:48
亚信安全携手统信软件,推出端点安全联合解决方案2025-11-05 02:43
电脑登QQ错误的解决方法(解决电脑登QQ出现错误的实用技巧)2025-11-05 02:35
较多邮件安全解决方案仍存在风险2025-11-05 02:22
Flyme5.1.6.0a(打造独特个性化的手机主题,尽享视觉盛宴)2025-11-05 04:33
研究人员发现一种新的网络钓鱼即服务——Frappo2025-11-05 04:22
攻击者部署后门,窃取Exchange电子邮件2025-11-05 04:02
mysql查询大小写问题2025-11-05 04:02
iPhone5s升级iOS8.1的全面指南(了解如何为iPhone5s安装最新的iOS8.1系统)2025-11-05 03:41
急眼了?美国再出手,悬赏1500万美元追查Conti黑客组织2025-11-05 03:38
一起学习MySQL源码笔记之偷窥线程2025-11-05 03:12
聚焦网信主业 中国长城2021年营收实现高速增长2025-11-05 02:42
小米5和5s拍照效果对比(小米5和5s相机表现如何?一图胜千言,你就知道!)2025-11-05 02:25
居家办公之难:工作效率与员工幸福度如何兼顾?2025-11-05 02:25