摘要
本文主要是重新理一下几个概念。经常发生一个对幻读错误的理解,比如场景:事务A 查询得到100条记录,事务B插入一条数据,事务B查询得到101条数据。很多人以为这是幻读场景,实际上不对,这属于不可重复读。MVCC机制就能解决这个问题。详见 Mysql中MVCC的使用及原理详解 这篇博客的示例。
幻读场景(假设id建立了唯一索引):比如 事务A查询id=1的数据,如果不存在,则插入id=1的这一行记录,在查询之后插入之前,事务B插入了id=1的记录,这时候事务A是查不到的,但是A是不能再插入id=1的数据行。
事务的ACID特性
原子性(A)
指处于同一个事务中的多条语句是不可分割的。要么就一起提交,要么就一起回滚,不存在部分提交,部分回滚。
一致性(C)
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。
隔离性(I)
指多线程环境下,一个线程中的事务不能被其他线程中的事务打扰
持久性(D)
事务一旦提交,就应该被永久保存起来。
事务的隔离级别概念
RU(Read uncommitted 未提交读)
事务A能读取到事务B中未提交的数据。
存在脏读,不可重复读,幻读的问题。
RC(Read committed 已提交读)
事务A能读取到事务B中已提交的数据。
解决脏读的问题,存在不可重复读,幻读的问题。
RR(REPEATABLE READ 可重复读)
同一个事务中,事务内部没有做更新的前提下,多次读出来的数据应该是一样的,不受别的事务操作影响。这里只解决脏读、不可重复读、不要求解决幻读。也就是说同一个事务中多次读出来的数据必须是一致的,但是,范围查询出来的条数可能不相等。
解决脏读,不可重复读的问题,存在幻读的问题,默认隔离级别,使用 MMVC机制 实现可重复读。
mysql 默认就是这个隔离级别. 这这种隔离级别实现的方法就是 MVCC,Mysql中MVCC的使用及原理详解。
Serializable (可串行化)
锁表,所有的操作都是串行的,这样就不存在脏读、幻读、不可重复读。
不同的隔离级别可能会导致的现象概念
脏读
一个事务中读取到了另一个事务未提交的数据。这个好理解。
幻读
幻读,并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。
解决这种问题的方法,就是加RangeS(范围锁)。
这里有个常见错误理解的场景:事务A查询全表有多少条数据,第一次查出来 100条,另一个事务B插入一条数据,这时候事务A再去查,查出来有101条数据。很多人以为这是幻读,实际上这不是。在RR隔离级别验证过,查出来的任然之后100条数据。
不可重复读
一个事务中读取到另一个事务中update的数据。这种的场景:事务A读取id=1对应的value=1,事务B这时候将id=1的value改成了2,事务A再去读,读到了id=1的value变成了2,也就是同一个事务里面两次读,读出来的结果不一致。
不同的事务隔离级别可能会到导致哪些现象的关系图
参考文档
MySQL脏读、不可重复读、幻读 (这里幻读理解错误)
来源:oschina
链接:https://my.oschina.net/liangxiao/blog/3130488