一、ResourceManager
二、AbstractResourceManager
三、DefaultResourceManager
四、TCCResourceManager
五、DataSourceManager
六、AsyncWorker
七、UndoLogManager
ResourceManager是seata的重要组件之一,RM负责管理分支数据资源的事务。它接口定义如下,实现ResourceManagerInbound以及ResourceManagerOutbound接口
public interface ResourceManager extends ResourceManagerInbound, ResourceManagerOutbound {
// 注册一个resource至事务管理器上
void registerResource(Resource resource);
// 从事务管理器上取消注册一个resource
void unregisterResource(Resource resource);
// 获取所有管理的resource
// @return resourceId -> Resource Map
Map getManagedResources();
// 获取此事务管理器的分支类型,有AT自动和TCC手动类型
BranchType getBranchType();
}
ResourceManagerInbound接口提供给TC进行rpc调用的方法
public interface ResourceManagerInbound {
// TM通知RM提交事务
BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException;
// TM通知RM回滚事务
BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException;
}
提供rpc请求至TC
public interface ResourceManagerOutbound {
// 请求注册分支resource
Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws
TransactionException;
// 报告分支状态
void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, String applicationData) throws TransactionException;
// 锁住query
boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys)
throws TransactionException;
}
AbstractResourceManager实现ResourceManager提供模板方法
public abstract class AbstractResourceManager implements ResourceManager {
// 创建BranchRegisterRequest请求,通过RmRpcClient客户端使用netty进行rpc调用,请求至TC,返回唯一的分支Id数据,
// 超时或报错抛出TransactionException
@Override
public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid, String applicationData, String lockKeys) throws TransactionException {
try {
BranchRegisterRequest request = new BranchRegisterRequest();
request.setXid(xid);
request.setLockKey(lockKeys);
request.setResourceId(resourceId);
request.setBranchType(branchType);
request.setApplicationData(applicationData);
BranchRegisterResponse response = (BranchRegisterResponse) RmRpcClient.getInstance().sendMsgWithResponse(request);
if (response.getResultCode() == ResultCode.Failed) {
throw new TransactionException(response.getTransactionExceptionCode(), "Response[" + response.getMsg() + "]");
}
return response.getBranchId();
} catch (TimeoutException toe) {
throw new TransactionException(TransactionExceptionCode.IO, "RPC Timeout", toe);
} catch (RuntimeException rex) {
throw new TransactionException(TransactionExceptionCode.BranchRegisterFailed, "Runtime", rex);
}
}
// 创建BranchReportRequest请求,通过RmRpcClient客户端使用netty进行rpc调用,请求至TC,返回唯一的分支Id数据,
// 超时或报错抛出TransactionException
@Override
public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status, String applicationData) throws TransactionException {
try {
BranchReportRequest request = new BranchReportRequest();
request.setXid(xid);
request.setBranchId(branchId);
request.setStatus(status);
request.setApplicationData(applicationData);
BranchReportResponse response = (BranchReportResponse) RmRpcClient.getInstance().sendMsgWithResponse(request);
if (response.getResultCode() == ResultCode.Failed) {
throw new TransactionException(response.getTransactionExceptionCode(), "Response[" + response.getMsg() + "]");
}
} catch (TimeoutException toe) {
throw new TransactionException(TransactionExceptionCode.IO, "RPC Timeout", toe);
} catch (RuntimeException rex) {
throw new TransactionException(TransactionExceptionCode.BranchReportFailed, "Runtime", rex);
}
}
// 默认返回false
public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys) throws TransactionException {
return false;
}
// 需子类实现
public void unregisterResource(Resource resource) {
throw new NotSupportYetException("unregister a resource");
}
// 调用RmRpcClient客户端,创建netty连接,进行rpc调用注册至全局tc
public void registerResource(Resource resource) {
RmRpcClient.getInstance().registerResource(resource.getResourceGroupId(), resource.getResourceId());
}
}
DefaultResourceManager是虚拟的ResourceManager,适配所有的ResourceManager,所有方法调用都委派给对应负责的ResourceManager处理。
public class DefaultResourceManager implements ResourceManager {
// 所有的ResourceManager缓存
protected static Map resourceManagers
= new ConcurrentHashMap<>();
// 构造方法初始化
private DefaultResourceManager() {
initResourceManagers();
}
// 单例模式
public static DefaultResourceManager get() {
return SingletonHolder.INSTANCE;
}
public static void mockResourceManager(BranchType branchType, ResourceManager rm) {
resourceManagers.put(branchType, rm);
}
// 初始化加载所有的ResourceManager,此处目前只有DataResourceManager和TCCResourceManager
protected void initResourceManagers() {
//init all resource managers
List allResourceManagers = EnhancedServiceLoader.loadAll(ResourceManager.class);
if (CollectionUtils.isNotEmpty(allResourceManagers)) {
for (ResourceManager rm : allResourceManagers) {
resourceManagers.put(rm.getBranchType(), rm);
}
}
}
@Override
public BranchStatus branchCommit(BranchType branchType, String xid, long branchId,
String resourceId, String applicationData)
throws TransactionException {
return getResourceManager(branchType).branchCommit(branchType, xid, branchId, resourceId, applicationData);
}
@Override
public BranchStatus branchRollback(BranchType branchType, String xid, long branchId,
String resourceId, String applicationData)
throws TransactionException {
return getResourceManager(branchType).branchRollback(branchType, xid, branchId, resourceId, applicationData);
}
@Override
public Long branchRegister(BranchType branchType, String resourceId,
String clientId, String xid, String applicationData, String lockKeys)
throws TransactionException {
return getResourceManager(branchType).branchRegister(branchType, resourceId, clientId, xid, applicationData,
lockKeys);
}
@Override
public void branchReport(BranchType branchType, String xid, long branchId, BranchStatus status,
String applicationData) throws TransactionException {
getResourceManager(branchType).branchReport(branchType, xid, branchId, status, applicationData);
}
@Override
public boolean lockQuery(BranchType branchType, String resourceId,
String xid, String lockKeys) throws TransactionException {
return getResourceManager(branchType).lockQuery(branchType, resourceId, xid, lockKeys);
}
@Override
public void registerResource(Resource resource) {
getResourceManager(resource.getBranchType()).registerResource(resource);
}
@Override
public void unregisterResource(Resource resource) {
getResourceManager(resource.getBranchType()).unregisterResource(resource);
}
@Override
public Map getManagedResources() {
Map allResource = new HashMap();
for (ResourceManager rm : resourceManagers.values()) {
Map tempResources = rm.getManagedResources();
if (tempResources != null) {
allResource.putAll(tempResources);
}
}
return allResource;
}
public ResourceManager getResourceManager(BranchType branchType) {
ResourceManager rm = resourceManagers.get(branchType);
if (rm == null) {
throw new FrameworkException("No ResourceManager for BranchType:" + branchType.name());
}
return rm;
}
private static class SingletonHolder {
private static DefaultResourceManager INSTANCE = new DefaultResourceManager();
}
}
TCCResourceManager继承AbstractResourceManager,管理TCC手动模式下resouce的注册,提交以及回滚等
public class TCCResourceManager extends AbstractResourceManager {
// TCC resource的缓存
private Map tccResourceCache = new ConcurrentHashMap();
/**
* Instantiates a new Tcc resource manager.
*/
public TCCResourceManager() {
}
// 放入缓存,调用父类注册至全局TC
@Override
public void registerResource(Resource resource) {
TCCResource tccResource = (TCCResource)resource;
tccResourceCache.put(tccResource.getResourceId(), tccResource);
super.registerResource(tccResource);
}
@Override
public Map getManagedResources() {
return tccResourceCache;
}
// TCC 分支提交
public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId,
String applicationData) throws TransactionException {
// 根据resourceId获取TCCResource
TCCResource tccResource = (TCCResource)tccResourceCache.get(resourceId);
if (tccResource == null) {
throw new ShouldNeverHappenException("TCC resource is not exist, resourceId:" + resourceId);
}
// 获取目标对象
Object targetTCCBean = tccResource.getTargetBean();
// 获取commit的方法
Method commitMethod = tccResource.getCommitMethod();
if (targetTCCBean == null || commitMethod == null) {
throw new ShouldNeverHappenException("TCC resource is not available, resourceId:" + resourceId);
}
try {
boolean result = false;
//BusinessActionContext
BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId,
applicationData);
// 提交方法反射调用
Object ret = commitMethod.invoke(targetTCCBean, businessActionContext);
LOGGER.info(
"TCC resource commit result :" + ret + ", xid:" + xid + ", branchId:" + branchId + ", resourceId:"
+ resourceId);
if (ret != null) {
if (ret instanceof TwoPhaseResult) {
result = ((TwoPhaseResult)ret).isSuccess();
} else {
result = (boolean)ret;
}
}
// 返回是否成功
return result ? BranchStatus.PhaseTwo_Committed : BranchStatus.PhaseTwo_CommitFailed_Retryable;
} catch (Throwable t) {
String msg = String.format("commit TCC resource error, resourceId: %s, xid: %s.", resourceId, xid);
LOGGER.error(msg, t);
throw new FrameworkException(t, msg);
}
}
// TCC 分支回滚
public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId,
String applicationData) throws TransactionException {
// 根据resourceId获取TCCResource
TCCResource tccResource = (TCCResource)tccResourceCache.get(resourceId);
if (tccResource == null) {
throw new ShouldNeverHappenException("TCC resource is not exist, resourceId:" + resourceId);
}
// 获取目标对象
Object targetTCCBean = tccResource.getTargetBean();
// 获取rollback的方法
Method rollbackMethod = tccResource.getRollbackMethod();
if (targetTCCBean == null || rollbackMethod == null) {
throw new ShouldNeverHappenException("TCC resource is not available, resourceId:" + resourceId);
}
try {
boolean result = false;
//BusinessActionContext
BusinessActionContext businessActionContext = getBusinessActionContext(xid, branchId, resourceId,
applicationData);
// 反射调用方法
Object ret = rollbackMethod.invoke(targetTCCBean, businessActionContext);
LOGGER.info(
"TCC resource rollback result :" + ret + ", xid:" + xid + ", branchId:" + branchId + ", resourceId:"
+ resourceId);
if (ret != null) {
if (ret instanceof TwoPhaseResult) {
result = ((TwoPhaseResult)ret).isSuccess();
} else {
result = (boolean)ret;
}
}
// 返回分支状态结果
return result ? BranchStatus.PhaseTwo_Rollbacked : BranchStatus.PhaseTwo_RollbackFailed_Retryable;
} catch (Throwable t) {
String msg = String.format("rollback TCC resource error, resourceId: %s, xid: %s.", resourceId, xid);
LOGGER.error(msg, t);
throw new FrameworkException(t, msg);
}
}
protected BusinessActionContext getBusinessActionContext(String xid, long branchId, String resourceId,
String applicationData) {
//transfer tcc applicationData to Context
Map tccContext = StringUtils.isBlank(applicationData) ? new HashMap() : (Map)JSON.parse(applicationData);
Map actionContextMap = (Map)tccContext.get(Constants.TCC_ACTION_CONTEXT);
BusinessActionContext businessActionContext = new BusinessActionContext(
xid, String.valueOf(branchId), actionContextMap);
businessActionContext.setActionName(resourceId);
return businessActionContext;
}
// 当前为TCC分支管理器
public BranchType getBranchType() {
return BranchType.TCC;
}
}
DataSourceManager继承AbstractResourceManager,管理数据库自动resouce的注册,提交以及回滚等
DataSourceManager继承AbstractResourceManager,管理数据库自动resouce的注册,提交以及回滚等
public class DataSourceManager extends AbstractResourceManager implements Initialize {
private ResourceManagerInbound asyncWorker;
private Map dataSourceCache = new ConcurrentHashMap<>();
public void setAsyncWorker(ResourceManagerInbound asyncWorker) {
this.asyncWorker = asyncWorker;
}
@Override
public boolean lockQuery(BranchType branchType, String resourceId, String xid, String lockKeys)
throws TransactionException {
try {
// 创建全球锁GlobalLockQueryRequest
GlobalLockQueryRequest request = new GlobalLockQueryRequest();
request.setXid(xid);
request.setLockKey(lockKeys);
request.setResourceId(resourceId);
GlobalLockQueryResponse response = null;
// 如果当前线程context已经是在全球事务处理中,则发送请求
if (RootContext.inGlobalTransaction()) {
response = (GlobalLockQueryResponse) RmRpcClient.getInstance().sendMsgWithResponse(request);
} else if (RootContext.requireGlobalLock()) {
// 或则开启了本地事务控制,能够获取到本地线程事务对象,进行负载均衡发送请求
response = (GlobalLockQueryResponse) RmRpcClient.getInstance().sendMsgWithResponse(loadBalance(),
request, NettyClientConfig.getRpcRequestTimeout());
} else {
throw new RuntimeException("unknow situation!");
}
if (response.getResultCode() == ResultCode.Failed) {
throw new TransactionException(response.getTransactionExceptionCode(),
"Response[" + response.getMsg() + "]");
}
return response.isLockable();
} catch (TimeoutException toe) {
throw new TransactionException(TransactionExceptionCode.IO, "RPC Timeout", toe);
} catch (RuntimeException rex) {
throw new TransactionException(TransactionExceptionCode.LockableCheckFailed, "Runtime", rex);
}
}
// 负载均衡,获取注册中心的所有socket地址列表,返回负载均衡下的address
private String loadBalance() {
InetSocketAddress address = null;
try {
List inetSocketAddressList = RegistryFactory.getInstance().lookup(
TmRpcClient.getInstance().getTransactionServiceGroup());
address = LoadBalanceFactory.getInstance().select(inetSocketAddressList);
} catch (Exception ignore) {
LOGGER.error(ignore.getMessage());
}
if (address == null) {
throw new FrameworkException(NoAvailableService);
}
return NetUtil.toStringAddress(address);
}
public DataSourceManager() {
}
// 实例化异步处理器,提供异步删除undo日志的方法
public void init() {
AsyncWorker asyncWorker = new AsyncWorker();
asyncWorker.init();
initAsyncWorker(asyncWorker);
}
// 注册DataSourceProxy resource,放入缓存,同时告知TC进行注册
public void registerResource(Resource resource) {
DataSourceProxy dataSourceProxy = (DataSourceProxy) resource;
dataSourceCache.put(dataSourceProxy.getResourceId(), dataSourceProxy);
super.registerResource(dataSourceProxy);
}
// 根据resourceId获取数据库的DataSource
public DataSourceProxy get(String resourceId) {
return (DataSourceProxy) dataSourceCache.get(resourceId);
}
// 提交成功,调用asyncWorker提交成功
public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException {
return asyncWorker.branchCommit(branchType, xid, branchId, resourceId, applicationData);
}
// 事务回滚
public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId, String applicationData) throws TransactionException {
DataSourceProxy dataSourceProxy = get(resourceId);
if (dataSourceProxy == null) {
throw new ShouldNeverHappenException();
}
try {
// 委派给UndoLogManager回滚已经提交的数据,将当前resouce的dataSourceProxy传入参数
UndoLogManager.undo(dataSourceProxy, xid, branchId);
} catch (TransactionException te) {
if (LOGGER.isInfoEnabled()){
LOGGER.info("branchRollback failed reason [{}]", te.getMessage());
}
if (te.getCode() == TransactionExceptionCode.BranchRollbackFailed_Unretriable) {
return BranchStatus.PhaseTwo_RollbackFailed_Unretryable;
} else {
return BranchStatus.PhaseTwo_RollbackFailed_Retryable;
}
}
return BranchStatus.PhaseTwo_Rollbacked;
}
@Override
public Map getManagedResources() {
return dataSourceCache;
}
// 此为AT自动模式管理器
public BranchType getBranchType() {
return BranchType.AT;
}
}
DataSourceManager事务提交委派给AsyncWorker进行提交的。因为都成功了,无需回滚成功的数据,只需要删除生成的
操作日志就行,采用异步方式,提高效率。
public class AsyncWorker implements ResourceManagerInbound {
private static ScheduledExecutorService timerExecutor;
@Override
public BranchStatus branchCommit(BranchType branchType, String xid, long branchId, String resourceId,
String applicationData) throws TransactionException {
if (!ASYNC_COMMIT_BUFFER.offer(new Phase2Context(branchType, xid, branchId, resourceId, applicationData))) {
LOGGER.warn("Async commit buffer is FULL. Rejected branch [" + branchId + "/" + xid
+ "] will be handled by housekeeping later.");
}
return BranchStatus.PhaseTwo_Committed;
}
// 初始化
public synchronized void init() {
LOGGER.info("Async Commit Buffer Limit: " + ASYNC_COMMIT_BUFFER_LIMIT);
// 创建定时器,每一秒定时doBranchCommits
timerExecutor = new ScheduledThreadPoolExecutor(1,
new NamedThreadFactory("AsyncWorker", 1, true));
timerExecutor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
doBranchCommits();
} catch (Throwable e) {
LOGGER.info("Failed at async committing ... " + e.getMessage());
}
}
}, 10, 1000 * 1, TimeUnit.MILLISECONDS);
}
// 分支提交具体方法
private void doBranchCommits() {
if (ASYNC_COMMIT_BUFFER.size() == 0) {
return;
}
// 获取需要2步执行的数据Phase2Context,并根据ResourceId进行分类
Map> mappedContexts = new HashMap<>(DEFAULT_RESOURCE_SIZE);
while (!ASYNC_COMMIT_BUFFER.isEmpty()) {
Phase2Context commitContext = ASYNC_COMMIT_BUFFER.poll();
List contextsGroupedByResourceId = mappedContexts.get(commitContext.resourceId);
if (contextsGroupedByResourceId == null) {
contextsGroupedByResourceId = new ArrayList<>();
mappedContexts.put(commitContext.resourceId, contextsGroupedByResourceId);
}
contextsGroupedByResourceId.add(commitContext);
}
// 遍历Map.Entry>
for (Map.Entry> entry : mappedContexts.entrySet()) {
Connection conn = null;
try {
try {
// 获取DataSourceManager
DataSourceManager resourceManager = (DataSourceManager)DefaultResourceManager.get()
.getResourceManager(BranchType.AT);
// 更加resourceId获取DataSourceProxy
DataSourceProxy dataSourceProxy = resourceManager.get(entry.getKey());
if (dataSourceProxy == null) {
throw new ShouldNeverHappenException("Failed to find resource on " + entry.getKey());
}
// 创建连接
conn = dataSourceProxy.getPlainConnection();
} catch (SQLException sqle) {
LOGGER.warn("Failed to get connection for async committing on " + entry.getKey(), sqle);
continue;
}
// 将缓存中的xid和branchId放入数组set中
List contextsGroupedByResourceId = entry.getValue();
Set xids = new LinkedHashSet<>(UNDOLOG_DELETE_LIMIT_SIZE);
Set branchIds = new LinkedHashSet<>(UNDOLOG_DELETE_LIMIT_SIZE);
// 获取当前resourceId下需要执行的commitContext
for (Phase2Context commitContext : contextsGroupedByResourceId) {
xids.add(commitContext.xid);
branchIds.add(commitContext.branchId);
int maxSize = xids.size() > branchIds.size() ? xids.size() : branchIds.size();
// 如果xid或branchId数组set中有一个等于批量操作1000条,就调用批量删除
if (maxSize == UNDOLOG_DELETE_LIMIT_SIZE) {
try {
// 调用UndoLogManager删除日志
UndoLogManager.batchDeleteUndoLog(xids, branchIds, conn);
} catch (Exception ex) {
LOGGER.warn("Failed to batch delete undo log [" + branchIds + "/" + xids + "]", ex);
}
xids.clear();
branchIds.clear();
}
}
if (CollectionUtils.isEmpty(xids) || CollectionUtils.isEmpty(branchIds)) {
return;
}
// 批量删除最后不满1000的数据
try {
UndoLogManager.batchDeleteUndoLog(xids, branchIds, conn);
} catch (Exception ex) {
LOGGER.warn("Failed to batch delete undo log [" + branchIds + "/" + xids + "]", ex);
}
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException closeEx) {
LOGGER.warn("Failed to close JDBC resource while deleting undo_log ", closeEx);
}
}
}
}
}
// 不支持回滚
public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId,
String applicationData) throws TransactionException {
throw new NotSupportYetException();
}
}
下面是UndoLogManager批量删除undo_log表中日志的逻辑,创建sql,然后批量设置参数,最后批量执行
public static void batchDeleteUndoLog(Set xids, Set branchIds, Connection conn) throws SQLException {
int xidSize = xids.size();
int branchIdSize = branchIds.size();
String batchDeleteSql = toBatchDeleteUndoLogSql(xidSize, branchIdSize);
PreparedStatement deletePST = null;
try {
deletePST = conn.prepareStatement(batchDeleteSql);
int paramsIndex = 1;
for (Long branchId : branchIds) {
deletePST.setLong(paramsIndex++, branchId);
}
for (String xid : xids) {
deletePST.setString(paramsIndex++, xid);
}
int deleteRows = deletePST.executeUpdate();
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("batch delete undo log size " + deleteRows);
}
} catch (Exception e) {
if (!(e instanceof SQLException)) {
e = new SQLException(e);
}
throw (SQLException)e;
} finally {
if (deletePST != null) {
deletePST.close();
}
}
}
下面是UndoLogManager回滚数据执行undo的逻辑
public static void undo(DataSourceProxy dataSourceProxy, String xid, long branchId) throws TransactionException {
assertDbSupport(dataSourceProxy.getDbType());
Connection conn = null;
ResultSet rs = null;
PreparedStatement selectPST = null;
for (; ; ) {
try {
//创建连接
conn = dataSourceProxy.getPlainConnection();
// The entire undo process should run in a local transaction.
//设置为自动提交
conn.setAutoCommit(false);
// Find UNDO LOG
selectPST = conn.prepareStatement(SELECT_UNDO_LOG_SQL);
selectPST.setLong(1, branchId);
selectPST.setString(2, xid);
// 执行查询,找到对应branchId和xid的数据
rs = selectPST.executeQuery();
boolean exists = false;
while (rs.next()) {
exists = true;
// 获取log_status,保证幂等性,只有正常状态的才能执行
int state = rs.getInt("log_status");
if (!canUndo(state)) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("xid {} branch {}, ignore {} undo_log",
xid, branchId, state);
}
return;
}
// 获取context
String contextString = rs.getString("context");
Map context = parseContext(contextString);
// 获取rollback_info
Blob b = rs.getBlob("rollback_info");
byte[] rollbackInfo = BlobUtils.blob2Bytes(b);
// 对rollbackInfo数据进行反序列化操作
String serializer = context == null ? null : context.get(UndoLogConstants.SERIALIZER_KEY);
UndoLogParser parser = serializer == null ? UndoLogParserFactory.getInstance() :
UndoLogParserFactory.getInstance(serializer);
BranchUndoLog branchUndoLog = parser.decode(rollbackInfo);
try {
// put serializer name to local
SERIALIZER_LOCAL.set(parser.getName());
// 循环调用创建sql执行
for (SQLUndoLog sqlUndoLog : branchUndoLog.getSqlUndoLogs()) {
TableMeta tableMeta = TableMetaCache.getTableMeta(dataSourceProxy, sqlUndoLog.getTableName());
sqlUndoLog.setTableMeta(tableMeta);
AbstractUndoExecutor undoExecutor = UndoExecutorFactory.getUndoExecutor(
dataSourceProxy.getDbType(),
sqlUndoLog);
undoExecutor.executeOn(conn);
}
} finally {
// remove serializer name
SERIALIZER_LOCAL.remove();
}
}
//如果undo_log存在,则意味着分支事务已经完成了第一阶段,我们可以直接回滚并清除undo_log日志。
//否则,表示分支事务中存在异常,导致无法将撤消日志写入数据库。
// 例如,业务处理超时,全局事务被发起方回滚。
// 为了保证数据的一致性,我们可以插入一个具有GlobalFinished状态undo_log日志,以防止其他程序第一阶段的本地事务被正确提交。
if (exists) {
// 存在,已经回滚日志了,进行删除
deleteUndoLog(xid, branchId, conn);
conn.commit();
if (LOGGER.isInfoEnabled()) {
LOGGER.info("xid {} branch {}, undo_log deleted with {}",
xid, branchId, State.GlobalFinished.name());
}
} else {
// 不存在undo_log日志则插入全球状态完成的日志
insertUndoLogWithGlobalFinished(xid, branchId, UndoLogParserFactory.getInstance(), conn);
conn.commit();
if (LOGGER.isInfoEnabled()) {
LOGGER.info("xid {} branch {}, undo_log added with {}",
xid, branchId, State.GlobalFinished.name());
}
}
return;
} catch (SQLIntegrityConstraintViolationException e) {
// Possible undo_log has been inserted into the database by other processes, retrying rollback undo_log
if (LOGGER.isInfoEnabled()) {
LOGGER.info("xid {} branch {}, undo_log inserted, retry rollback",
xid, branchId);
}
} catch (Throwable e) {
if (conn != null) {
try {
conn.rollback();
} catch (SQLException rollbackEx) {
LOGGER.warn("Failed to close JDBC resource while undo ... ", rollbackEx);
}
}
throw new TransactionException(BranchRollbackFailed_Retriable, String.format("%s/%s", branchId, xid),
e);
} finally {
try {
if (rs != null) {
rs.close();
}
if (selectPST != null) {
selectPST.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException closeEx) {
LOGGER.warn("Failed to close JDBC resource while undo ... ", closeEx);
}
}
}
}