Spring中事务的5种属性总结
Sping的事务 和 数据库的事务是不同的概念,数据库的事务一般称为底层事务
Spring的事务是对这种事务的抽象 我称之为逻辑事务
Spring对事务的功能进行了扩展,除了基本的Isolation之外,增加了PROPAGATION传播特性,Timeout属性,readOnly属性 ,回滚条件
Isolation是作用于物理属性的
PROPAGATION传播特性 是通过spring自己的事务管理实现的事务嵌套的处理逻辑
Timeout属性,readOnly属性 则都是作用于Connection上的
下面我把Spring中的事务的5中属性归纳如下
在spring中 事务有5个属性
- 传播特性
- 隔离级别
- 回滚规则
- 事务超时
- 是否只读
除了回滚规则外 其他的属性都定义在TransactionDefinition的实现类里面
一般来讲 就是DefaultTransactionDefinition了
回滚规则的判断体现在接口TransactionAttribute里面 实现则是在RuleBasedTransactionAttribute里面
1.传播特性PROPAGATION:
新的事务应该被启动还是挂起?方法是否要在事务的环境中运行?
- PROPAGATION_MANDATORY 方法必须在事务中运行,如果没有事务就要抛出错误 MANDATORY 是强制的意思
- PROPAGATION_NESTED 嵌套,外层有事务的情况下 如果内层要打开事务就打开事务嵌套运行,如果内层没有事务就加入到上层事务中去,嵌套事务是可以独立提交和回滚的 (对于jdbc Spring其实在内层没有开启新事务,只是在内层方法前设置了savepoint)
- PROPAGATION_NEVER 表示这个方法不能运行在事务中,如果上下文有事务 就要抛出异常
- PROPAGATION_NOT_SUPPORTED 表示当前方法运行的时候 如果有上下文事务,那么上下文事务会被挂起 等该方法执行结束,上下文事务恢复
- PROPAGATION_REQUIRED 表示当前方法必须运行在事务中,如果上下文有事务就加入上下文事务;上下文没有事务,就启动一个新事务
- PROPAGATION_REQUIRES_NEW 当前方法一定会启动自己的事务,如果有上下文事务,上下文事务会被挂起的 (对于jdbc Spring在内层开启新事务(创建了新的Connection 内层事务是独立的开启 提交 回滚的)
- PROPAGATION_SUPPORTS 表示当前方法不需要上下文事务,但是如果有上下文事务的话 还是可以在上下文事务里运行的
2.隔离级别ISOLATION
一个事务,可能受其他并发事务的影响程度
3个问题:
脏读: 事务A在执行过程中 读取到了事务B修改过但是尚未提交的数据
不可重复读: 事务A读取了两次,两次结果不同, 原因是中途事务B修改了数据并且提交了
幻读: 事务A读取了3行数据 过了一会再读取读出来4条数据, 原因是事务B中途insert了一条数据; 多出来的这一条数据叫做幻影数据
- ISOLATION_DEFAULT 数据库默认隔离级别 mysql的话 就是read_committed
- ISOLATION_READ_UNCOMMITTED 读未提交 会导致脏读, 但是也是效率最高的一种级别
- IOSLATION_READ_COMMITTED 读已提交,最常用的的级别,可以防止脏读
- ISOLATION_REPEATABLE_READ 可重复读, 能防止脏读和重复读, 但是防不了幻读
- ISOLATION_SERIALIZABLE 最高级别,可防幻读
3.只读 readOnly
private boolean readOnly = false; public final void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } public final boolean isReadOnly() { return this.readOnly; }
4.事务超时 timeOut
private int timeout = TIMEOUT_DEFAULT; public final void setTimeout(int timeout) { if (timeout < TIMEOUT_DEFAULT) { throw new IllegalArgumentException("Timeout must be a positive integer or TIMEOUT_DEFAULT"); } this.timeout = timeout; } public final int getTimeout() { return this.timeout; }
5.回滚规则
private List<RollbackRuleAttribute> rollbackRules; public void setRollbackRules(List<RollbackRuleAttribute> rollbackRules) { this.rollbackRules = rollbackRules; } public List<RollbackRuleAttribute> getRollbackRules() { if (this.rollbackRules == null) { this.rollbackRules = new LinkedList<RollbackRuleAttribute>(); } return this.rollbackRules; } //判断当前抛出的异常是否要回滚 public boolean rollbackOn(Throwable ex) { RollbackRuleAttribute winner = null; int deepest = Integer.MAX_VALUE; if (this.rollbackRules != null) { for (RollbackRuleAttribute rule : this.rollbackRules) { int depth = rule.getDepth(ex); if (depth >= 0 && depth < deepest) { deepest = depth; winner = rule; } } } if (logger.isTraceEnabled()) { logger.trace("Winning rollback rule is: " + winner); } // User superclass behavior (rollback on unchecked) if no rule matches. if (winner == null) { logger.trace("No relevant rollback rule found: applying default rules"); return super.rollbackOn(ex); } return !(winner instanceof NoRollbackRuleAttribute); //判断winner是否是不回滚的异常类型 }
学无止境-----博客均为原创,转载请注明出处