Spring事务隔离级别比数据库事务隔离级别多一个default,由低到高为:
DEFAULT (默认)
数据库默认的是可重复读
READ_UNCOMMITTED (读未提交):允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
A查询表student,可以看到初始数据“张三20岁”,在A提交事务之前,B对student表进行更新修改“张三22岁”,虽然B没有提交事务,但是可以在A中查询到B刚修改的数据“张三22岁”,如果B回滚的话,那么A原先查询到的“张三22岁”就是脏数据,A再次查询的数据还是“张三20岁”;
READ_COMMITTED (读已提交):允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
A查询表student,可以看到初始数据“张三20岁”,在A提交事务之前,B对student表进行更新修改“张三22岁”,此时A查询数据还是“张三20岁”,没有脏读,B提交后A查询,此时A查询数据为“张三22岁”,和“张三20岁”不一致,从而产生了不可重复读的问题
REPEATABLE_READ (可重复读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
A查询表student,可以看到初始数据“张三20岁”,在A提交事务之前,B对student表进行更新修改“张三22岁”并提交,此时A查询数据仍为“张三20岁”,没有出现不可重复读的问题;A继续执行更新操作使张三年龄+2,然后查询张三年龄变为24,因为是按B操作之后的值计算的,因此数据一致性没有问题;在这个隔离级别下,它使用了MVCC机制,select是快照读(历史版本),不会更新版本号,insert、update和delete是当前读(当前版本),会更新版本号;
SERIALIZABLE(串行化)并发性极低
A和B都修改表student的第一行,那么这行就会被锁定,谁先碰到第一行谁先操作它,只有当事务提交了,这一行才会解锁,后一个事务才能成功操作这个数据行,否则只能一直等待,可能导致大量的超时现象和锁竞争。
简单说一下脏读、不可重复度还有幻读:
脏读:A将1改为2,这时B读到2,但A又将此数据回滚到1,这时B就是脏读
不可重复读(update或delete):A读取到1,但这时B将数据改为2,A再读的时候是2,两次数据不一致
幻读(insert):A读取到有1条数据,这时B插入了1条数据变成了2条,A再读的时候发现数据多了1条,A第一次读的比第二次读的少