From 48658f079d1ab1e3038f1b2c8284ea4b04875bcc Mon Sep 17 00:00:00 2001 From: shukai Date: Thu, 13 Feb 2025 17:29:15 +0800 Subject: [PATCH] bugfix:Transfer global timeout and branch transaction begin time --- .../apache/seata/core/context/RootContext.java | 13 +++++++++++++ .../rm/datasource/xa/ConnectionProxyXA.java | 18 +++++++++++++----- .../seata/tm/api/DefaultGlobalTransaction.java | 2 ++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/apache/seata/core/context/RootContext.java b/core/src/main/java/org/apache/seata/core/context/RootContext.java index 85453afb5d1..96b042ba4d7 100644 --- a/core/src/main/java/org/apache/seata/core/context/RootContext.java +++ b/core/src/main/java/org/apache/seata/core/context/RootContext.java @@ -59,6 +59,11 @@ private RootContext() { * The constant KEY_TIMEOUT. */ public static final String KEY_TIMEOUT = "TX_TIMEOUT"; + + /** + * The constant KEY_BRANCH_BEIGN_TIME. + */ + public static final String KEY_BRANCH_BEIGN_TIME = "TX_BRANCH_BEIGN_TIME"; /** * The constant MDC_KEY_XID for logback @@ -141,6 +146,14 @@ public static Integer getTimeout() { public static void setTimeout(Integer timeout) { CONTEXT_HOLDER.put(KEY_TIMEOUT,timeout); } + + public static Long getBranchBeignTime() { + return (Long) CONTEXT_HOLDER.get(KEY_BRANCH_BEIGN_TIME); + } + + public static void setBranchBeignTime(Long branchBeignTime) { + CONTEXT_HOLDER.put(KEY_BRANCH_BEIGN_TIME,branchBeignTime); + } /** * declare local transactions will use global lock check for update/delete/insert/selectForUpdate SQL diff --git a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXA.java b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXA.java index 709263d88cc..94d08910a0c 100644 --- a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXA.java +++ b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/xa/ConnectionProxyXA.java @@ -27,6 +27,7 @@ import org.apache.seata.common.lock.ResourceLock; import org.apache.seata.common.util.StringUtils; import org.apache.seata.config.ConfigurationFactory; +import org.apache.seata.core.context.RootContext; import org.apache.seata.core.exception.TransactionException; import org.apache.seata.core.model.BranchStatus; import org.apache.seata.core.model.BranchType; @@ -62,11 +63,11 @@ public class ConnectionProxyXA extends AbstractConnectionProxyXA implements Hold private volatile boolean rollBacked = false; - private volatile Long branchRegisterTime = null; + private volatile Long branchBeginTime = null; private volatile Long prepareTime = null; - private static final Integer TIMEOUT = Math.max(BRANCH_EXECUTION_TIMEOUT, DefaultValues.DEFAULT_GLOBAL_TRANSACTION_TIMEOUT); + private volatile Integer timeout = null; private boolean shouldBeHeld = false; @@ -93,6 +94,15 @@ public void init() { if (!currentAutoCommitStatus) { throw new IllegalStateException("Connection[autocommit=false] as default is NOT supported"); } + Integer transactionTimeout = RootContext.getTimeout(); + if (transactionTimeout == null) { + transactionTimeout = DefaultValues.DEFAULT_GLOBAL_TRANSACTION_TIMEOUT; + } + timeout = Math.max(BRANCH_EXECUTION_TIMEOUT, transactionTimeout); + branchBeginTime = RootContext.getBranchBeignTime(); + if(branchBeginTime == null) { + branchBeginTime = System.currentTimeMillis(); + } } catch (SQLException e) { throw new RuntimeException(e); } @@ -190,7 +200,6 @@ public void setAutoCommit(boolean autoCommit) throws SQLException { long branchId; try { // 1. register branch to TC then get the branch message - branchRegisterTime = System.currentTimeMillis(); branchId = DefaultResourceManager.get().branchRegister(BranchType.XA, resource.getResourceId(), null, xid, null, null); } catch (TransactionException te) { @@ -318,7 +327,6 @@ private synchronized void end(int flags) throws XAException, SQLException { private void cleanXABranchContext() { xaEnded = false; - branchRegisterTime = null; prepareTime = null; xaActive = false; if (!isHeld()) { @@ -327,7 +335,7 @@ private void cleanXABranchContext() { } private void checkTimeout(Long now) throws XAException { - if (now - branchRegisterTime > TIMEOUT) { + if (now - branchBeginTime > timeout) { xaRollback(xaBranchXid); throw new XAException("XA branch timeout error"); } diff --git a/tm/src/main/java/org/apache/seata/tm/api/DefaultGlobalTransaction.java b/tm/src/main/java/org/apache/seata/tm/api/DefaultGlobalTransaction.java index 8fb4b3ca326..2e13bd2e9b1 100644 --- a/tm/src/main/java/org/apache/seata/tm/api/DefaultGlobalTransaction.java +++ b/tm/src/main/java/org/apache/seata/tm/api/DefaultGlobalTransaction.java @@ -113,6 +113,8 @@ public void begin(int timeout, String name) throws TransactionException { xid = transactionManager.begin(null, null, name, timeout); status = GlobalStatus.Begin; RootContext.bind(xid); + RootContext.setTimeout(timeout); + RootContext.setBranchBeignTime(createTime); if (LOGGER.isInfoEnabled()) { LOGGER.info("Begin new global transaction [{}]", xid); }