搞懂mysql事物隔离级别

事物是为交易而生

事物的英文单词 TRANSACTION,就是交易的意思. 交易和事物是一个东西.

mysql的事物的4种隔离级别

mysql的事物隔离级设计的一点也不高级
隔离级别只是一个很烧脑的概念,并不是什么高大上的技术.

  1. RU,全称read-uncommitted, 中文翻译:读未提交,能够读到未提交的数据,就是不隔离
  2. RC,全称read-committed,中文翻译:读已提交,能读到已提交的数据.
  3. RR,全称repeatable-read,中文翻译:可重复读. 也有人管这个叫当前读.
  4. 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里面很多概念理解起来很烧脑.都是为了解决一些问题造出了一堆概念,解决一个老问题就会产生一个新问题,如此循环无穷尽也.

 

你可能感兴趣的:(java,数据库,服务器)