本项目聚焦高并发的基础知识,至底向上得研究:

github 仓库 (分支 master / isolation / propagation / multithreading)

理念:
Spring Boot 和基于Groovy的测试框架Spock编写测试用例。master 分支 isolation 分支propagation 分支 <===== 本文坐标multithreading 分支事务传播行为官网描述
用于区分声明式事务catch到异常由框架回滚,本文的“回滚”用到编程式事务的API TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 支持主动回滚。编程式事务官网描述
讨论的模型是 调用方(外层) -> 被调用方(内层)
默认传播行为, 确保当前方法一定处于事务保护中
UnexpectedRollbackException因为内层加入到外层事务中,形成一个大事务,TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 会把外层的代码一并提交,内层代码执行完毕,外层代码继续执行。由于声明式事务,外层代码执行结束,会触发一次提交,但是这次提交的事务已经被内层提交了,所以抛异常。
用于减少事务的粒度,如果不是关键的业务逻辑或是运行出错的逻辑,可以用requires_new 声明与调用方事务隔离。
requiredrequired 的异常只适用于JDBC。介于required 和 nested 之间,内层事务处于一个“寄生”的状态,他的附加价值是可以减少死锁隐患,后文会提到。
requiredrequires_newrequires_new 造成的死锁分析requires_new 声明的内层事务B由于事务A和事务B属于不同事务,A未提交并持有record的写锁不释放,
事务B一直等待A释放,事务A又等待事务B提交自己才能提交。所以互相等待,造成锁等待超时。
nested 取代 requires_new 减少死锁隐患nested 声明的内层事务被外层调用,视为“寄生”在外层的事务中。也就不存在事务竞争资源。
同时 nested 支持独立回滚,是由底层JDBC的savepoint 支持,API例子:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
status.createSavepoint();
status.rollbackToSavepoint();
}
}