事物是为交易而生
事物的英文单词 TRANSACTION,就是交易的意思. 交易和事物是一个东西.
mysql的事物的4种隔离级别
mysql的事物隔离级设计的一点也不高级
隔离级别只是一个很烧脑的概念,并不是什么高大上的技术.
- RU,全称read-uncommitted, 中文翻译:读未提交,能够读到未提交的数据,就是不隔离
- RC,全称read-committed,中文翻译:读已提交,能读到已提交的数据.
- RR,全称repeatable-read,中文翻译:可重复读. 也有人管这个叫
当前读
. - SERIALIZABLE,中文翻译:序列化,串行执行.
从上到下越来越严格,性能也越来越差.
mysql默认的隔离级是哪种?
默认是第三种,RR可重复读
隔离性是什么?
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。 即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
隔离的了什么?
隔离的是事物中间状态产生的数据.
- 什么是中间状态?
一个事物中包含了多个sql, 还没有全部执行完成,只完成了一部分sql,还没有提交,这就是中间状态的数据. 隔离的就是这时候的数据. 这个时间虽然很短暂,但是程序并发执行的时候会出现,一个事物还未执行完,另一个事物就开始执行了,开始查数据了.
第二个事物是否可以看见第一个事物中已经修改了,但是还未提交的数据呢?这就是隔离级别考虑的问题.
选择哪个隔离级别呢
第一种 RU 完全不隔离, 会出现脏读,基本不用.
第四种完全实现了ACID,解决脏读、不可重复读、幻读,可保证事务安全,但完全串行执行,性能最低 ,由于性能太差,互联网应用并发大,一般不用.
然后剩下RR,RC. 都避免了脏读,事物更新数据后,还未提交时,对其他事物是不可见的.它们读到的是更新之前的数据.
RC 解决脏读的问题,存在不可重复读、幻读的问题
RR是mysql 默认级别,解决脏读、不可重复读的问题,存在幻读的问题。使用 MMVC机制 实现可重复读
- RC,RR的区别是什么?
能不能可重复读.
可重复读
和不可重复读
有什么区别?
一个事物在执行过程中,能不能读到其他事物已经提交的事物对数据的更新呢?
如果能读到数据的变化,就是不可重复读,
如果不能读到数据的变化,就是可重复读.
不可重复读
是什么情况?
在同一个事务内两次读取同一条数据,读到的结果可能会不一样,这就是“不可重复读”。
可重复读
的情况是什么?
本次事物开启后, 其他事物对数据的修改 我也不管,就当看不见, 即使其他事物已经修改了数据,我再查询的时候,还是得到老数据.
这个隔离级别更高.
说的是本次事物可重复读.不受其他事物影响.
那么RC,RR选哪个?
其实选哪个都行,
有一个兼顾两种隔离级别的方案.
就是乐观锁, 数据表增加版本号字段, 先查数据,更新的时候限定更新where的条件带上查询到的版本号.
执行结果判断一下影响的结果行数要等于1才是更新成功.
因为即使where条件没有符合的数据,也不会返回失败.而是影响的结果为0.
就能防止在这个时候,其他事物突然更新了数据造成数据异常.
这样就控制了并发更新.
并发事物会出现哪些问题?
在事务的并发操作中可能会出现脏读,不可重复读,幻读。
什么是幻读?什么情况出现?
幻读会在 RU / RC / RR 级别下出现,SERIALIZABLE 则杜绝了幻读,
幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。
mysql 幻读的详解、实例及解决办法 - 个人文章 - SegmentFault 思否
锁 与 隔离级别
某个隔离级别默认带了某些锁,但是可以单独加锁.
update语句是会更新已提交的事物的数据.也就是对当前最新数据进行更新
update语句是自带for update的.
SERIALIZABLE 隔离级别下会隐式为你加行X锁
X是根据你的查询条件计算的行的范围
间隙锁是行锁的升级版,间隙锁比行锁范围大一点.
加锁的目的是防止当前事物被其他事物干扰.
也就是说,即使把所有的记录都加上锁,还是阻止不了新插入的记录,这也是为什么“幻读”会被单独拿出来解决的原因。
for update的bug
查询语句加上for update 会查询到当前数据库最新的数据, 其他事物已经提交的数据都能看到.
所以for update的查询也叫 当前读.
解决幻读
为了解决幻读问题,innodb引入了间隙锁(Gap lock).顾名思义,就是锁住两个值之间的空隙.
间隙锁容易导致死锁.
间隙锁在可重复读隔离级别下才有效
next-key lock 实际上是由间隙锁加行锁实现的。
当使用唯一索引来搜索唯一行的语句时,不需要间隙锁定。只使用行锁. 否则会使用间隙锁
如果,搜索条件里有多个查询条件(即使每个列都有唯一索引),也是会有间隙锁的。
幻读还是很难解决的,
可以用乐观锁解决.
MVVC
相当于一个快照
MVCC(Multi Version Concurrency Control的简称),代表多版本并发控制。与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control)。
MVCC最大的优势:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能
原理:一致性视图, InnoDB 在实现 MVCC 时用到的一致性读视图,即 consistent read view,用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现。
这个视图不是那个我们可以自己创建的视图,是两个概念.
数据表中的一行记录,其实可能有多个版本 (row),每个版本有自己的 row trx_id 作为版本号 来区分.
mysql里面很多概念理解起来很烧脑.都是为了解决一些问题造出了一堆概念,解决一个老问题就会产生一个新问题,如此循环无穷尽也.