Seata 怎么让子事物中其中一张表不参与全局事物?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在 Seata 中,如果需要让子事务中的某张表不参与全局事务,可以通过以下方式实现:
@GlobalTransactional
和 @Transactional
的组合Seata 的全局事务通过 @GlobalTransactional
注解开启,而本地事务则通过 Spring 的 @Transactional
注解管理。如果希望某张表的操作不参与全局事务,可以将该操作放在一个独立的本地事务中,并确保其不被 @GlobalTransactional
包裹。
实现步骤: - 将不参与全局事务的操作封装到一个独立的方法中。 - 在该方法上仅使用 @Transactional
注解,而不使用 @GlobalTransactional
。 - 确保该方法的调用路径不在全局事务的上下文中。
示例代码:
@Service
public class OrderService {
@GlobalTransactional
public void createOrder() {
// 全局事务逻辑
updateInventory();
deductAccountBalance();
// 调用不参与全局事务的方法
logOperationLocally();
}
@Transactional
public void logOperationLocally() {
// 仅本地事务逻辑,不参与全局事务
operationLogRepository.save(new OperationLog("Order created"));
}
}
关键点: - logOperationLocally
方法仅使用 @Transactional
,因此其操作不会被纳入 Seata 的全局事务管理范围。
Seata 通过代理数据源(如 DataSourceProxy
)来拦截 SQL 操作并将其纳入全局事务管理。如果希望某张表的操作不参与全局事务,可以绕过 Seata 的代理数据源,直接使用原始数据源。
实现步骤: - 配置一个未被 Seata 代理的原始数据源。 - 在需要排除全局事务的操作中,显式使用该原始数据源。
示例代码:
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource rawDataSource() {
return new DruidDataSource();
}
@Bean("globalDataSourceProxy")
public DataSource globalDataSourceProxy(DruidDataSource rawDataSource) {
return new DataSourceProxy(rawDataSource); // Seata 代理数据源
}
@Bean("localDataSource")
public DataSource localDataSource() {
return rawDataSource(); // 原始数据源,不参与全局事务
}
}
@Service
public class LogService {
@Autowired
@Qualifier("localDataSource")
private DataSource localDataSource;
public void logOperation() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(localDataSource);
jdbcTemplate.update("INSERT INTO operation_log (message) VALUES (?)", "Local operation logged");
}
}
关键点: - localDataSource
是未被 Seata 代理的原始数据源,因此其操作不会被纳入全局事务管理。
如果使用 Seata 的 TCC(Try-Confirm-Cancel)或 Saga 模式,可以通过手动定义事务边界来控制哪些操作参与全局事务。
实现步骤: - 在 TCC 模式下,为需要排除的操作单独定义一个分支事务,并在 try
、confirm
和 cancel
方法中明确指定其行为。 - 在 Saga 模式下,通过状态机定义事务流程,跳过不需要参与全局事务的操作。
示例代码(TCC 模式):
@TwoPhaseBusinessAction(name = "logOperationTcc")
public class LogOperationTccAction {
@Override
public boolean prepare(BusinessActionContext context) {
// 不执行任何操作,直接返回成功
return true;
}
@Override
public boolean commit(BusinessActionContext context) {
// 记录日志操作
logRepository.save(new Log("Operation logged"));
return true;
}
@Override
public boolean rollback(BusinessActionContext context) {
// 不需要回滚操作
return true;
}
}
关键点: - 在 TCC 模式下,prepare
方法可以为空操作,从而避免该分支事务对全局事务的影响。
通过上述方法,您可以灵活地控制 Seata 子事务中某些表的操作是否参与全局事务,满足特定业务需求。