springboot事务的传播行为和隔离级别
1. 在springboot中事务的传播行为和隔离级别都是在TransactionDefinition这个接口中定义的
- 传播行为定义了7种,分别用0-6来表示
int PROPAGATION_REQUIRED = 0;//如果当前上下文中的已经存在一个事务,就使用当前的事务;如果当前没有事务就创建一个新的事务int PROPAGATION_SUPPORTS = 1;//如果当前上下文中的已经存在一个事务,就使用当前的事务;如果当前没有事务也不会开启一个新事务,以非事务的方式执行int PROPAGATION_MANDATORY = 2;//如果当前上下文中的已经存在一个事务,就使用当前的事务;如果当前没有事务就抛出异常int PROPAGATION_REQUIRES_NEW = 3;//如果当前上下文中的已经存在一个事务,就暂停该事务;创建一个新的事务开始执行。完成后恢复之前挂起的事务int PROPAGATION_NOT_SUPPORTED = 4;//不支持事务,如果当前上下文中已经存在一个事务,就挂起事务;已非事务的方式执行int PROPAGATION_NEVER = 5;//不支持事务,如果当前上下文中已经存在一个事务,就抛出异常int PROPAGATION_NESTED = 6;//如果当前上下文中已经存在事务,就开启一个嵌套的事务。简单来说就是不管当前上下文中是否存在事务,本次都会创建一个事务
- 隔离级别有4种
int ISOLATION_DEFAULT = -1;//默认的隔离级别,使用数据库当前的隔离级别。会是后面四种隔离级别的其中一种int ISOLATION_READ_UNCOMMITTED = 1;//读未提交;会有脏读,不可重复读,幻读发生int ISOLATION_READ_COMMITTED = 2; //读已提交;会有不可重复读,幻读发生int ISOLATION_REPEATABLE_READ = 4; //重复读;会有幻读出现int ISOLATION_SERIALIZABLE = 8; //串行化
关于脏读、不可重复读、幻读引用《深入浅出MySQL:数据库开发、优化与管理维护(第2版》中的描述吧
脏读(Dirty Reads):一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做“脏读”。
不可重复读(Non-Repeatable Reads):一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变或某些记录已经被删除了!这种现象就叫做“不可重复读”。
幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读”。
关于各种隔离级别的描述可以参考我之前的文章隔离性与隔离级别
2. 关于事务属性的默认值,对于springboot来说Transactional注解中定义的。我们可以在定义我们的事务的时候,根据实际需要修改这些属性值
@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Inherited@Documentedpublic @interface Transactional {@AliasFor("transactionManager")String value() default "";@AliasFor("value")String transactionManager() default "";String[] label() default {};Propagation propagation() default Propagation.REQUIRED;//默认的传播行为Isolation isolation() default Isolation.DEFAULT;//默认的隔离级别int timeout() default -1;String timeoutString() default "";boolean readOnly() default false;Class<? extends Throwable>[] rollbackFor() default {};String[] rollbackForClassName() default {};Class<? extends Throwable>[] noRollbackFor() default {};String[] noRollbackForClassName() default {};}