spring-transaction脑图
2020-11-18 11:04:47 2 举报
AI智能生成
登录查看完整内容
为你推荐
查看更多
spring-transaction
作者其他创作
大纲/内容
传播级别
required
需要事务,可以复用上层事务
required_new
需要事务,不可以复用上层事务,挂起上层事务,并新建事务
not_support
不支持事务,如果有事务,则挂起上层事务
support
支持事务,可以复用事务,没有事务就无事务运行
nested
不对上层事务做操作,创建savePoint,本事务回滚不影响上层事务,上层事务回滚影响当前事务
never
不支持事务,有事务就报错
mandatory
必须要有事务,没有就报错
传播级别的实现,是java代码实现的,savePoint需要数据库支持
隔离级别
default
默认的意思就是,如果有上层事务,则沿用上层事务的隔离级别,如果没有就用当前数据库的隔离级别(会报warn)
if (def.getIsolationLevel() != ISOLATION_DEFAULT && this.logger.isWarnEnabled()) { this.logger.warn(\"Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored: \" + def); }
read_uncommited
read_commited
repeatable_read
serializable
隔离级别的实现,是通过修改数据库的连接的隔离级别来实现的
坑
1. 隔离级别最好选用defalut
如果说选择的required/supports/mandatory三种情况,但是隔离级别选跟当前上层事务的隔离级别不同的情况下,就会报错!
if (definition.getIsolationLevel() != ISOLATION_DEFAULT) { Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel(); if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) { Constants isoConstants = DefaultTransactionDefinition.constants; throw new IllegalTransactionStateException(\"Participating transaction with definition [\" + definition + \"] specifies isolation level which is incompatible with existing transaction: \
2. readOnly的事务最好是独立的
也就是readOnly的事务里,如果存在其他事务的可能,也会报错!
if (!definition.isReadOnly() && TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { throw new IllegalTransactionStateException(\"Participating transaction with definition [\" + definition + \"] is not marked as read-only but existing transaction is\"); }
3. 内部事务回滚后,外部事务把exception捕获了会导致回滚失败而报错
tx
TransactionInterceptor.invoke
TransactionAspectSupport.invokeWithinTransaction
1. 获取transactionManager
TransactionManager tm = this.determineTransactionManager(txAttr);
tm配置在spring-tx.xsd,默认是PlatformTranactionManager
2. 获取方法/类上的事务信息
3. createTransactionIfNecessary
1. 也就是AbstractPlatformTransactionManager.getTransaction() 根据事务配置来获取事务信息
getTransaction
doGetTransaction
获取DataSourceTransactionObject
ConnectionHolder
currentConnection
transactionActive
savepointsSupported
savepointCounter
savePointAllowed
previousIsolationLevel
mustRestoreAutoCommit
handleExistingTransaction
1. never
报错
2. not support
挂起当前事务
suspend
清空threadLocal中的synchronization的信息(ThransactionManager)
TransactionSynchronizationManager.clearSynchronization();
清空threadLocal中datasource(ThransactionManager)
TransactionSynchronizationManager.unbindResource(this.obtainDataSource());
清空ThransactionManager中的currentTransation的信息
TransactionSynchronizationManager.setCurrentTransactionName((String)null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel((Integer)null);
TransactionSynchronizationManager.setActualTransactionActive(false);
把suspend的事务信息转存在SuspendedResourcesHolder上
suspend跟resume就是反作用
3. required new
挂起当前事务,并创建新事务
startTransaction
创建TransactionStatus,newTransaction=true
doBegin
获取连接
如果没有就创建新连接
设置数据库的隔离级别和readOnly(设置为transaction配置的级别)
if (definition != null && definition.getIsolationLevel() != ISOLATION_DEFAULT) { if (debugEnabled) { logger.debug(\"Changing isolation level of JDBC Connection [\" + con + \"] to \" + definition.getIsolationLevel()); }\t//设置当前connection的隔离级别为transaction定义的隔离级别--原来不同连接的隔离可以随时改的。 int currentIsolation = con.getTransactionIsolation(); if (currentIsolation != definition.getIsolationLevel()) { previousIsolationLevel = currentIsolation; con.setTransactionIsolation(definition.getIsolationLevel()); } }
stmt.executeUpdate(\"SET TRANSACTION READ ONLY\");
关闭自动提交,设置MustRestoreAutoCommit
txObject.setMustRestoreAutoCommit(true);
顾名思义,就是要记得恢复autoCommit
con.setAutoCommit(false);
最后把conn作为datasource关联到当前的线程当中
prepareSynchronization
初始化当前线程中跟transation有关的ThreadLocal变量
TransactionSynchronizationManager
失败则resume
异常情况:resumeAfterBeginException
如果有挂起的事务,则把挂起的事务的datasource绑定到当前线程
设置currentTransaction为之前挂起的事务信息
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive); TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel); TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly); TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
重新注册之前活跃的synchronization信息(TranactionManager)
Iterator var2 = suspendedSynchronizations.iterator(); while(var2.hasNext()) { TransactionSynchronization synchronization = (TransactionSynchronization)var2.next(); synchronization.resume(); TransactionSynchronizationManager.registerSynchronization(synchronization); }
4. nested
使用savepoint
调用底层创建savePoint
createAndHoldSavepoint
获取当前的conn
conHolder.createSavepoint()
++this.savepointCounter
this.getConnection().setSavepoint(\"SAVEPOINT_\" + this.savepointCounter);
自动提交的情况下,不能新增savePoint,会报错
\"Cannot establish a savepoint in auto-commit mode.\
stmt.executeUpdate(\"SAVEPOINT \" + savepoint.getPGName());
不使用savePoint
创建新事务
5. else 也就是复用当前事务
校验isolation 和 readOnly是否跟当前事务匹配
不匹配,报错
匹配,构造TransactionStatus返回
nonExisting
supports/not_supported/never
直接构造一个TransactionStatus返回
required/required_new/nested
返回TransactionStatus
transactionObject
newTransaction boolean
readOnly
suspendedResource
挂起的事务,resume或者回滚的时候用
2. 创建txInfo,记住上层txInfo,并绑定到线程上
4. 执行方法
retVal = invocation.proceedWithInvocation();
5. 报错处理
判断事务中是否配置rollbackOn如果有则rollback
rollback
this.triggerBeforeCompletion(status);
1. savePoint场景:rollbackToHeldSavepoint
//调用conn的rollbackToSavepoint接口 conHolder.getConnection().rollback((Savepoint)savepoint); conHolder.resetRollbackOnly();// 设置为false
2. isNewTransactoin,也就是当前事务是独立的事务
conn直接执行rollback
设置conn的rollbackOnly=true
this.doSetRollbackOnly(status);
异常,如果unexpected=true则抛错
this.cleanupAfterCompletion(status);
1. 解绑datasource
2. 恢复conn的自动提交
3. 恢复隔离界别,readonly
4. 释放conn
5. 清空connectionHolder的savePoint事务状态等
没有就commit
6. 没有异常则commit
commit
1. 如果status已经完成,则抛错
2. 如果transaction配置的时候就是rollbackOnly,则回滚
status.rollbackOnly
3. 如果内部事务回滚,则回滚
isGlobalRollbackOnly:设置在ConnectionHolder中
4. 如果都不是,则提交
收藏
收藏
0 条评论
回复 删除
下一页