脏读
脏读是两个并发的事务1和事务2在执行时,事务1读取了事务2尚未提交的数据,而事务2由于出现异常回滚了,事务1拿着读到的事务2的数据进行后续操作时就出现数据错误了,脏读了。如下图:
不可重复读
事务1中读取了某个数据,同时事务2也在修改这个数据,在事务2修改完这个数据并提交事务后,事务1又一次读取了这个数据,两次读取的同一数据就会不一致,这种现象叫做不可重复读。如图所示:
幻读
事务1中首先读取了某一业务(比如交易记录数)记录数,此时并发的事务2新增了一条交易记录,并提交事务,此时事务1再次读取交易记录数时,记录数前后就会出现不一致,这种现象称为幻读。如图所示:
事务隔离级别
事务隔离级别的设置能部分规避上述出现的3个问题,下面看下spring中事务隔离级别的配置。
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional { @AliasFor("transactionManager") String value() default ""; @AliasFor("value") String transactionManager() default ""; Propagation propagation() default Propagation.REQUIRED; Isolation isolation() default Isolation.DEFAULT; int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; boolean readOnly() default false; Class<? extends Throwable>[] rollbackFor() default {}; String[] rollbackForClassName() default {}; Class<? extends Throwable>[] noRollbackFor() default {}; String[] noRollbackForClassName() default {}; }
package org.springframework.transaction.annotation; import org.springframework.transaction.TransactionDefinition; public enum Isolation { //使用所连接数据库的默认隔离级别(比如mysql默认是REPEATABLE_READ)。 DEFAULT(TransactionDefinition.ISOLATION_DEFAULT), //未提交读 READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED), //已提交读 READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED), //可重复读 REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ), //串行化 SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE); private final int value; Isolation(int value) { this.value = value; } public int value() { return this.value; } }
事务隔离级别与可能出现的并发事务问题的关系如下: