1.脏写
脏写,写的数据,过了一会儿莫名其妙没了。
例:有两个事务,事务A和事务B同时在更新一条数据,事务A先把它更新为A值,事务B紧接着把它更新为B值,如下图所示
此时,事务A在执行之前,这行数据可能值是NULL,事务A的undo log日志大概就是:更新之前这行数据值为NULL,主键为xx;如果事务B将这行数据更新为B,此时事务A突然回滚,那么就会用他的undo log日志去回滚;事务A一回滚,直接就会把这行数据的值更新回之前的NULL值;此时,事务B就会觉得,我明明更新成了B值,为什么还是NULL。
2.脏读
脏读,读到其他事务未提交的数据。
例:事务B去查询事务A修改过的数据,但是此时事务A还没提交,所以事务A随时会回滚,导致事务B再次查询就读不到刚才事务A修改过的数据了。
3.不可重复读
不可重复读,多次读到其他事务提交的数据,多次读取结果不一致。
例:缓存页里有一条数据原来的值是A值,此时事务A开启,第一次查询这条数据,读取到的就是A值;接着,事务B更新这行数据的值为B值,同时事务B立马提交了,此时事务A是没提交的,他在事务执行期间第二次查询数据,此时查到的是事务B修改过的值,B值,这就导致了A事务多次查询同一条数据的值不一致.
可重复读就是事务A多次查询同一条数据的值不变。
4.幻读
幻读,一个事务用同样的SQL多次查询,每次查询都会查到一些之前没查到过的数据。
例:事务A发送一条SQL”select from table”,查询出来10条数据;这个时候,事务B往表里新插入两条数据,并且提交事务B;事务A再次执行”select from table”,结果查出来12条数据。
5.不可重复读与幻读的区别
两者都是读取了其他事务已经提交的数据。
不可重复读是由于另一个事务对数据的更改所造成的,而幻读是由于另一个事务插入或删除引起的。
6.SQL标准的事务隔离级别
在SQL标准中规定了四种事务隔离级别,就是说多个事务并发运行的时候,相互是如何隔离的,从而避免一些事务并发问题。
- read uncommintted(读未提交):不允许发生脏写,不可能两个事务在没提交的情况下去更新同一行数据的值,可能发生脏读、不可重复读、幻读。不推荐使用。
- read commintted(读已提交):不会发生脏写和脏读,事务没提交情况下修改的值,是觉得读不到的,可能会发生不可重复读和幻读。
- repeatable read(可重复读):不会发生脏写、脏读和不可重复读,一个事务多次查询一个数据的值,那怕别的事务修改了这个值还提交了,也不会读到别的事务修改的值。可以保证同一行数据的多次查询,不会读到不一样的值,但依然可能发生幻读。
- serializable(序列化):不允许多个事务并发执行,只能串行执行,性能极差。不要使用。
7.MySQL事务隔离级别
MySQL默认设置的事务隔离级别,是RR(repeatable read)级别的,并且MySQL的RR级别可以避免幻读发生。也就是说,MySQL里面执行事务,默认情况下不会发生脏写、脏读、不可重复读和幻读。-- level的值可以是REPEATABLE READ、READ COMMITTED、READ UNCOMMITTED、SERIALIZABLESET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL <level>;
8.Spring事务隔离级别
在@Transactional注解中有一个isolation参数,可以设置事务隔离级别。
@Transactional(isolation=Isolation.DEFAULT),然后默认的就是DEFAULT值,这个就是MySQL默认支持什么隔离级别就是什么隔离级别。也可以改成Isolation.READ_COMMITTED,Isolation.REPEATABLE_READ,Isolation.SERIALIZABLE几个级别。
