Understanding Seata: Principles, Deployment, and Real‑World Issues in Distributed Transactions
This article introduces Seata's background, explains the causes of data inconsistency in micro‑service architectures, details Seata's three core roles, transaction flow, isolation levels, common pitfalls with code examples, and provides guidance on high‑availability deployment, multi‑node setups, disaster recovery, and hands‑on demos.
Background
Seata is a distributed transaction middleware adopted by Yixian e‑commerce to solve data inconsistency problems caused by rapid growth of services and complex call chains.
Problem Background
In micro‑service environments, data inconsistency arises from business exceptions, network failures, and service unavailability.
Business Introduction
The article uses simple Yixian e‑commerce scenarios to illustrate the problem.
Principle Analysis
Seata consists of three roles:
Transaction Manager (TM) – client side
Resource Manager (RM) – client side
Transaction Coordinator (TC) – server side
It proxies SQL execution to capture before‑image, after‑image, and undo log for each statement, ensuring atomicity of business and undo‑log operations.
Check that the data source is successfully proxied if a transaction appears ineffective.
First Phase (Prepare)
When an interface annotated with @GlobalTransactional is called, TM intercepts the call, TC creates a global transaction (XID) and returns it. The XID is propagated through the call chain until the end of execution.
Ensure XID is correctly passed down; otherwise the transaction may not work.
Second Phase Commit
If no exception occurs, TC cleans global transaction data and RM removes the corresponding undo log.
Second Phase Rollback
On exception, Seata triggers reverse rollback (C → B → A). If the undo log is missing (e.g., branch registration succeeded but response lost), RM persists a special undo log with status GlobalFinished to prevent inconsistency.
Isolation Level – Read Committed
Seata defaults to READ_UNCOMMITTED. To upgrade to READ_COMMITTED, use @GlobalLock and add FOR UPDATE to the query.
@GlobalLock
@Transactional
public PayMoneyDto detail(ProcessOnEventRequestDto dto) {
return baseMapper.detail(dto.getProcessInfoDto().getBusinessKey());
}
@Mapper
public interface PayMoneyMapper extends BaseMapper<PayMoney> {
@Select("select id, name, amount, account, has_repayment, pay_amount from pay_money m where m.business_key = #{businessKey} for update")
PayMoneyDto detail(@Param("businessKey") String businessKey);
}Common Issues
TableMeta cache problem : Seata caches table metadata; if the schema changes without restarting the application, a NullPointerException may occur.
@Override
public TableMeta getTableMeta(final Connection connection, final String tableName, String resourceId) {
if (StringUtils.isNullOrEmpty(tableName)) {
throw new IllegalArgumentException("TableMeta cannot be fetched without tableName");
}
final String key = getCacheKey(connection, tableName, resourceId);
TableMeta tmeta = TABLE_META_CACHE.get(key, mappingFunction -> {
try {
return fetchSchema(connection, tableName);
} catch (SQLException e) {
LOGGER.error("get table meta of the table `{}` error: {}", tableName, e.getMessage(), e);
return null;
}
});
if (tmeta == null) {
throw new ShouldNeverHappenException(String.format("[xid:%s]get table meta failed, please check whether the table `%s` exists.", RootContext.getXID(), tableName));
}
return tmeta;
}Solution: restart the application after schema changes.
Branch and lock table residue : In MySQL master‑slave setups, data may not sync to the slave, causing missing branch records and global lock acquisition failures.
@Override
public GlobalStatus commit(String xid) throws TransactionException {
GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
if (globalSession == null) {
return GlobalStatus.Finished;
}
globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
boolean shouldCommit = SessionHolder.lockAndExecute(globalSession, () -> {
globalSession.closeAndClean();
if (globalSession.getStatus() == GlobalStatus.Begin) {
if (globalSession.canBeCommittedAsync()) {
globalSession.asyncCommit();
return false;
} else {
globalSession.changeStatus(GlobalStatus.Committing);
return true;
}
}
return false;
});
if (shouldCommit) {
boolean success = doGlobalCommit(globalSession, false);
if (success && globalSession.hasBranch() && globalSession.canBeCommittedAsync()) {
globalSession.asyncCommit();
return GlobalStatus.Committed;
} else {
return globalSession.getStatus();
}
} else {
return globalSession.getStatus() == GlobalStatus.AsyncCommitting ? GlobalStatus.Committed : globalSession.getStatus();
}
}Similar logic applies to rollback.
High‑Availability Deployment
Deploy multiple TC instances with the same registry and configuration center (e.g., Nacos, Consul, etcd3, Zookeeper). Use store.mode=db for persistence.
Single‑Node Multi‑Application Deployment
Use vgroup‑mapping to isolate groups of applications on the same node.
Cross‑Region Disaster Recovery
Configure separate registries for different data centers (e.g., Guangzhou and Shanghai) and switch groups instantly when a region fails.
# Guangzhou data center
registry {
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
cluster = "Guangzhou"
}
}
# Shanghai data center
registry {
type = "nacos"
loadBalance = "RandomLoadBalance"
loadBalanceVirtualNodes = 10
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
cluster = "Shanghai"
}
}Demo
Online hands‑on experience is available at https://start.aliyun.com and a specific Seata demo at https://start.aliyun.com/handson/isnEO76f/distributedtransaction .
Recommended Reading
Links to articles on Kafka architecture, design methodology, and database‑cache consistency are provided for further study.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
