什么是脏读: 读到没有commit的数据
什么是不可重复读:同一个事务中,两次读取到的数据不一样。
什么是幻读:
同一个事务中,两次读取到的数据不一样。这个流程看起来和不可重复读差不多,但幻读强调的集合的增减,而不是单独一条数据的修改。最常见的场景便是
事务的隔离级别
1 | select @@global.tx_isolation; |
级别逐级别提高,越高数据隔离的越彻底。可是代价是付出性能。
value 为0
读未提交(Read Uncommitted),在这个级别下,所有事务都能看到其他未提交的事务的数据,基本很少用到。
value 为1
一个事务只能看见已经提交事务所做的改变。解决脏读的问题,存在不可重复读,幻读的问题。
可重复读 REPEATABLE-READ | 2
MySQL默认的级别,解决脏读,不可重复读。但是存在幻读的。接下来就是要讨论如何避免了。
序列化 SERIALIZABLE | 3
强迫事务排序,串行执行事务,从而杜绝上面的所有问题,但是会带来大量的等待,基本没有使用。
在RR(READTABLE-READ)级别下,如何避免幻读,答案是显式加锁。
简单的场景:
A 事务:查询表是否存在id=10000,如果无,就插入数据。
就在插入的前一刻,另外一个事务插入了id=10000的数据,此刻A事务就会莫名收到数据已经存在的错误,也无法插入成功。这就是典型的幻读了。如何解决呢,用SELECT FOR UPDATE,无论数据是否存在,都会被加上锁。(当记录不存在的时候,mysql 会给索引加上gap间隙锁,对此可以模拟一下哦)