mysql如何实现4种事务隔离级别
MySQL 事务隔离级别
MySQL InnoDB事务的隔离级别有四级,默认是“可重复读”(REPEATABLE READ)。
未提交读(READ UNCOMMITTED)。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)。
提交读(READ COMMITTED)。本事务读取到的是最新的数据(其他事务提交后的)。问题是,在同一个事务里,前后两次相同的SELECT会读到不同的结果(不重复读)。
可重复读(REPEATABLE READ)。在同一个事务里,SELECT的结果是事务开始时时间点的状态,因此,同样的SELECT操作读到的结果会是一致的。但是,会有幻读现象(稍后解释)。
串行化(SERIALIZABLE)。读操作会隐式获取共享锁,可以保证不同事务间的互斥。
四个级别逐渐增强,每个级别解决一个问题。
脏读,最容易理解。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据。
这个可以通过读已提交解决。
不重复读。解决了脏读后,会遇到,同一个事务执行过程中,另外一个事务提交了新数据,因此本事务先后两次读到的数据结果会不一致。
对当前数据加行锁解决。
幻读。解决了不重复读,保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。但是,如果另一个事务同时提交了新数据,本事务再更新时,就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。
通过MVCC+间隙锁解决
MySQL 事务实现原理
事务的实现是基于数据库的存储引擎,不同的存储引擎对事务的支持程度不一样。MySQL 中支持事务的存储引擎有InnoDB 和 NDB。 InnoDB 是高版本 MySQL 的默认的存储引擎,因此就以 InnoDB 的事务实现为例,InnoDB 是通过多版本并发控制(MVCC,Multiversion Concurrency Control )解决不可重复读问题,加上间隙锁(也就是并发控制)解决幻读问题。因此 InnoDB 的 RR 隔离级别其实实现了串行化级别的效果,而且保留了比较好的并发性能。
什么是MVCC?
MVCC 全称是多版本并发控制系统,InnoDB 和 Falcon 存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决幻读问题。
innoDB 的 MVCC 是通过在每行记录后面保存两个隐藏的列来实现,这两个列一个保存了行的创建时间,一个保存行的过期时间(删除时间)。当然存储的并不是真实的时间而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动新增,事务开始时刻的系统版本号会作为事务的版本号,用来查询到每行记录的版本号进行比较。
在RR隔离级别下,MVCC的操作如下:
select操作
InnoDB只查找版本早于(包含等于)当前事务版本的数据行。可以确保事务读取的行,要么是事务开始前就已存在,或者事务自身插入或修改的记录。
行的删除版本要么未定义,要么大于当前事务版本号。可以确保事务读取的行,在事务开始之前未删除。
insert操作
将新插入的行保存当前版本号为行版本号。
delete操作
将删除的行保存当前版本号为删除标识。
update操作
insert和delete操作的组合,insert的行保存当前版本号为行版本号,delete则保存当前版本号到原来的行作为删除标识。
这篇文章已经举了例子:
https://www.cnblogs.com/myseries/p/10930910.html
简要把例子概括一下:
第一步:事务A插入3条记录:
innoDB为新插入的每一行保存当前系统版本号作为版本号. 第一个事务ID为1;start transaction;
insert into yang values(NULL,'yang') ;
insert into yang values(NULL,'long');
insert into yang values(NULL,'fei');
commit;
事务A查询结果:select * from yang ;
第二步:事务B插入一条数据
另一个事务ID为3往这个表里插入了一条数据; 第三个事务ID为3;start transaction;
insert into yang values(NULL,'tian');
commit;
事务B的查询结果:
事务A这个时候的查询结果:select * from yang ;
事务A的查询结果没变,因为:
select * from yang ; 这个普通查询语句属于快照读。使用多版本并发控制MVCC保证事务。
InnoDB会根据以下两个条件检查每行记录:
a.InnoDB只会查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的.
b.行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除.
只有a,b同时满足的记录,才能返回作为查询结果.
快照读和当前读
当前读:select...lock in share mode (共享读锁)select...for updateupdate , delete , insert
当前读:
单纯的select操作,不包括上述 select ... lock in share mode, select ... for update。
第3步:事务C删除并更新了一条数据:
start transaction;
delete from yang where id=1;
update yang set name='Long' where id=2;
commit;
当前数据库中的实际状态是:
事务A读到的是:select * from yang;
事务A的查询结果没变,因为还是上面的:
select * from yang ; 这个普通查询语句属于快照读。使用多版本并发控制MVCC保证事务。
InnoDB会根据以下两个条件检查每行记录:
a.InnoDB只会查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的.
b.行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除.
只有a,b同时满足的记录,才能返回作为查询结果.
但是如果事务A这个时候用当前读sql去读:select * from yang for update
得到的是当前最新的记录。也就是当前读查询出了其他事务新插入的行。
结论:
对于使用MVCC的可重复读(REPEATABLE READ)隔离级别。普通的快照读,已经解决不可重复读和幻读的问题,同时没有使用锁,并发性能高。但是,快照读读取的都是历史数据,并没有解决当前读情况下的幻读问题:即可以看到其他数据的新增。所以需要通过间隙锁来保证当前读情况下的幻读问题
间隙锁:
间隙锁:只有在Read Repeatable、Serializable隔离级别才有,就是锁定范围空间的数据。
比如:
select * from yang where id>2 for update;
id>2的记录全部被锁住了,其他事务无法更新id>2的所有记录。包括新增id=6的记录。
因为此时如果不锁定没有的数据,例如当加入了新的数据id=6,就会出现幻读,间隙锁避免了幻读。
间隙锁注意事项:
1.对主键或唯一索引,如果当前读时,where条件全部精确命中(=或者in),这种场景本身就不会出现幻读,所以只会加行记录锁。
2.没有索引的列,当前读操作时,会加全表gap锁,生产环境要注意。
3.非唯一索引列,如果where条件部分命中(>、<、like等)或者全未命中,则会加附近Gap间隙锁。例如,某表数据如下,非唯一索引2,6,9,9,11,15。如下语句要操作非唯一索引列9的数据,gap锁将会锁定的列是(6,11],该区间内无法插入数据。
结论:
对于可重复度隔离级别,如果普通读也用间隙锁那就和串行化没有区别了,并发性能很差。所以使用MVCC实现了读的非阻塞,提升了读性能。可是无法避免当前读情况下的幻读,所以加上间隙锁可以手工保证实现不出现幻读。
参考资料:
https://www.cnblogs.com/myseries/p/10930910.html
https://www.cnblogs.com/tiancai/p/12053126.html
http://blog.sina.com.cn/s/blog_499740cb0100ugs7.html
https://www.cnblogs.com/wwcom123/p/10727194.html
mysql如何实现4种事务隔离级别相关推荐
- mysql四种事务级别_【MySQL 知识】四种事务隔离级别
摘要:本篇文章主要是为了对MySQL的四种事务隔离级别的介绍.为了保证数据库的正确性与一致性,数据库事务具有原子性(Atomicity).一致性(Consistency).隔离性(Isolation) ...
- js hbs mysql_实例分析MySQL下的四种事务隔离级别
数据库事务有四种隔离级别: 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据. 提交读(Read Committed):只能读取到已经提交的数据, ...
- mysql四种事务隔离级别
mysql事务并发问题 ACID什么的就不啰嗦了.mysql多个事务并发的时候,可能会出现如下问题: 1. 更新丢失 即两个事务同时更新某一条数据,后执行的更新操作会覆盖先执行的更新操作,导致先执行的 ...
- mysql四种输入_mysql四种事务隔离级别
mysql事务并发问题 ACID什么的就不啰嗦了.mysql多个事务并发的时候,可能会出现如下问题: 1. 更新丢失 即两个事务同时更新某一条数据,后执行的更新操作会覆盖先执行的更新操作,导致先执行的 ...
- 【MySQL】MySQL的四种事务隔离级别
[MySQL]MySQL的四种事务隔离级别 本文实验的测试环境:Windows 10+cmd+MySQL5.6.36+InnoDB 一.事务的基本要素(ACID) 1.原子性(Atomicity):事 ...
- Mysql有四种事务隔离级别,详解脏读、不可重复读、幻读
Mysql的事务隔离级别 Mysql有四种事务隔离级别,这四种隔离级别代表当存在多个事务并发冲突时,可能出现的脏读.不可重复读.幻读的问题. 脏读 大家看一下,我们有两个事务,一个是 Transact ...
- Spring 有几种事务隔离级别?
Spring 中的事务隔离级别和数据库中的事务隔离级别稍有不同,以 MySQL 为例,MySQL 的 InnoDB 引擎中的事务隔离级别有 4 种,而 Spring 中却包含了 5 种事务隔离级别. ...
- Java面试题之Oracle 支持哪三种事务隔离级别
Oracle 支持三种事务隔离级别: 1.读已提交:(默认) 2.串行化: 3.只读模式 转载于:https://www.cnblogs.com/hujinshui/p/10463883.html
- InnoDB的几种事务隔离级别
前文 首先理解事务的ACID的隔离性 并发带来的问题,脏读 .不可重复读 .幻读 的问题. 脏读: 一个事务读取了另一个事务未提交的数据,导致数据不一致.[事务2未提交] 不可重复读: 一个事务前后两 ...
最新文章
- CentOS6.8 Redis5 开机自动启动命令设置
- ASP.NET MVC – 样式和布局简介
- (转)datagridview 自定义列三步走
- SAP2014年最新版本EHP7安装经验分享
- pond and pool
- 2018年澳门就业情况理想 最新失业率维持1.7%
- 实战|QUIC协议助力腾讯业务提速30%
- iframe URI钓鱼
- css画个框,用CSS绘制带有边框的尖端
- Module的加载实现
- C# 使用Conditional特性而不是#if条件编译
- [游戏开发-学习笔记]菜鸟慢慢飞(12)- Unity3D中LitJson 解析遇到的问题
- 使用Docker Swarm来运行服务
- 联想 M7400 两种清零方法
- 【Spring】源码浅析 - ResponseEntity.ok
- Android红外功能模拟触摸鼠标事件唤醒屏幕
- 踩坑谷歌浏览器翻译插件自动创建font节点
- 三、向SpringCloud注册Service服务(Restful服务)
- OpenGL ES 模拟器
- 指数函数误差平方和matlab,数值分析与实验数学081 张燃 3080801119).doc
热门文章
- 苹果微信多开能装多少个?
- 美国金融业监管局严厉批评“SAFT”ICO框架
- php的表达爱意的一句代码,爱表达的唯美句子大全 浪漫表达爱意的句子12个字
- 网站收录量,反链,关键词排名,权重相关问题
- 冒泡排序(BubbleSort)
- java实现快速排序法
- python能为我们做什么读后感作文_请根据影片《告白》写下自己的观后感!
- 简书 android bug记录,记录工作中的Bug
- Android中图案解锁的设计原理和实现过程
- css6图层 解锁,OpenLayers6实例分析:Layer Spy(图层探查)