1. 政务系统中的事务管理挑战
在政务系统开发中,工作流引擎与业务数据库的事务一致性一直是个棘手问题。我们团队2015年承接某省级政务审批系统时,就遇到了Activiti工作流与业务库事务隔离的难题。当时系统要求:当业务审批流程流转时,业务数据变更与流程节点更新必须保持原子性——要么全部成功,要么全部回滚。
传统方案是在Service层用Spring声明式事务管理,但实际运行中发现了几个致命问题:
- Activiti默认使用独立事务,与业务操作不在同一个Connection生命周期
- 跨数据源场景下,分布式事务性能无法满足政务系统高并发要求
- 事务回滚时存在工作流引擎状态与业务数据不一致的风险
经过多次压力测试,我们发现当并发量超过200TPS时,采用XA协议的分布式事务方案会导致系统响应时间飙升到不可接受的程度。这促使我们寻找更轻量级的解决方案。
2. JdbcTransaction扩展方案设计
2.1 核心思路解析
MyBatis的JdbcTransaction实现给我们提供了突破口。通过分析源码发现:
public class JdbcTransaction implements Transaction { protected Connection connection; protected DataSource dataSource; // 关键方法 public Connection getConnection() throws SQLException { if (connection == null) { openConnection(); } return connection; } }我们的改造方案分为三步走:
- 创建CustomJdbcTransaction继承原生JdbcTransaction
- 重写事务管理方法,实现Connection共享
- 通过ThreadLocal机制保证多线程环境下的连接隔离
2.2 具体实现代码
public class SharedJdbcTransaction extends JdbcTransaction { private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<>(); @Override public Connection getConnection() throws SQLException { Connection conn = connectionHolder.get(); if (conn == null) { conn = dataSource.getConnection(); conn.setAutoCommit(false); connectionHolder.set(conn); } return conn; } @Override public void commit() throws SQLException { Connection conn = connectionHolder.get(); if (conn != null && !conn.getAutoCommit()) { conn.commit(); connectionHolder.remove(); } } }关键点在于:
- 使用ThreadLocal保证线程安全
- 只在首次获取连接时设置autoCommit=false
- 提交后立即清理ThreadLocal防止内存泄漏
3. Activiti集成改造
3.1 事务工厂注入
需要在MyBatis配置中替换默认事务工厂:
<transactionManager type="com.gov.SharedJdbcTransactionFactory"> <property name="dataSource" ref="dataSource"/> </transactionManager>对应的工厂类实现:
public class SharedJdbcTransactionFactory implements TransactionFactory { @Override public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) { return new SharedJdbcTransaction(ds, level, autoCommit); } }3.2 Activiti配置调整
修改activiti.cfg.xml中的事务配置:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <property name="transactionManager" ref="transactionManager"/> <property name="dataSource" ref="dataSource"/> </bean>4. 实战中的坑与解决方案
4.1 连接泄漏问题
在初期版本中,我们遇到过连接未及时关闭的情况。解决方案是增加finally块中的清理逻辑:
@Override public void close() throws SQLException { Connection conn = connectionHolder.get(); if (conn != null) { try { if (!conn.getAutoCommit()) { conn.rollback(); } conn.close(); } finally { connectionHolder.remove(); } } }4.2 嵌套事务处理
政务系统中存在多级审批的场景,需要支持事务嵌套。我们通过引用计数机制实现:
private static ThreadLocal<AtomicInteger> transactionDepth = new ThreadLocal<>(); @Override public void begin() { AtomicInteger depth = transactionDepth.get(); if (depth == null) { depth = new AtomicInteger(0); transactionDepth.set(depth); } depth.incrementAndGet(); }5. 性能优化实践
5.1 连接池调优
政务系统对稳定性要求极高,我们针对Druid连接池做了特别配置:
# 初始连接数 druid.initialSize=5 # 最大活跃连接数 druid.maxActive=50 # 获取连接超时时间(毫秒) druid.maxWait=3000 # 连接有效性检查SQL druid.validationQuery=SELECT 1 FROM DUAL5.2 事务超时控制
为防止长事务阻塞系统,增加了超时回滚机制:
public class TimeoutAwareTransaction extends SharedJdbcTransaction { private long beginTime; private static final long TIMEOUT = 30000; // 30秒 @Override public void begin() { super.begin(); this.beginTime = System.currentTimeMillis(); } @Override public Connection getConnection() throws SQLException { checkTimeout(); return super.getConnection(); } private void checkTimeout() { if (System.currentTimeMillis() - beginTime > TIMEOUT) { throw new TransactionTimeoutException("Transaction timeout after 30s"); } } }6. 安全合规考量
政务系统对安全性有严格要求,我们在事务管理中特别处理了:
- SQL注入防护:所有流程变量都经过预编译处理
- 审计日志:记录关键事务操作日志
- 敏感数据加密:审批内容在事务提交前自动加密
审计日志实现示例:
public class AuditLogTransaction extends SharedJdbcTransaction { @Override public void commit() throws SQLException { auditLogService.logTransaction( "COMMIT", getTransactionId(), getCurrentUser() ); super.commit(); } }7. 生产环境验证
这套方案在省级政务系统上线后,经历了完整压力测试:
- 连续7天稳定性测试,TPS保持在500以上
- 模拟200并发用户持续操作8小时无故障
- 异常断电测试中事务一致性保持100%
监控数据显示:
- 平均事务响应时间:78ms
- 最大事务深度:5层
- 日均事务量:12万次
8. 扩展应用场景
除了政务系统,该方案还适用于:
- 金融行业审批流程
- 医疗电子病历系统
- 电商订单履约系统
- 物流跟踪管理系统
在医疗系统中使用时,需要特别注意HIPAA合规要求,我们在事务管理中增加了患者隐私数据保护层:
public class HippaCompliantTransaction extends SharedJdbcTransaction { @Override public void commit() throws SQLException { encryptSensitiveData(); super.commit(); cleanTemporaryData(); } }这套基于MyBatis事务扩展的方案,经过8年生产环境验证,在保持高性能的同时完美解决了工作流与业务数据的一致性问题。核心价值在于:
- 避免引入重量级分布式事务框架
- 保持原生JDBC性能优势
- 实现真正的原子性操作
对于需要深度定制事务管理的场景,这种"外科手术式"的精准改造,往往比套用现成框架更能满足复杂业务需求。