activiti工作流发起流程时出现事务冲突的优化方案
【问题】
由于bpm流程是通过监听策略进行触发执行一些操作(如审核通过、不通过、取消等),导致数据库查询、修改同时对一个表操作,导致流程发起失败等情况。
【方案】
-
优化数据库设计
1.1 索引优化
确保流程实例ID(PROC_INST_ID_)、任务ID(TASK_ID_)、执行ID(EXECUTION_ID_)等高频查询字段建立索引,减少锁竞争。1.2 避免全表扫描
通过EXPLAIN分析慢查询,优化涉及ACT_RU_TASK、ACT_RU_EXECUTION等运行时表的SQL。 -
避免长事务
拆分业务逻辑,将非核心操作(如日志、通知)移出事务:
@Transactional
public void startProcess()
{
// 1. 启动流程(短事务)
ProcessInstance instance = runtimeService.startProcessInstanceByKey("approval");
// 2. 异步处理耗时操作
asyncService.sendNotification(instance.getId()); // 非事务方法
}
-
锁顺序控制
统一资源操作顺序,若需更新多个流程实例,按ID排序后操作,避免交叉锁引发死锁。
List<String> instanceIds = Arrays.asList("id1", "id2", "id3");
Collections.sort(instanceIds); // 强制排序
instanceIds.forEach(id -> {
runtimeService.setVariable(id, "status", "approved");
});
-
重试机制
捕获死锁异常并重试方案
public void safeStartProcess()
{
int retries = 3;
while (retries-- > 0)
{
try
{
runtimeService.startProcessInstanceByKey("approval");
break;
}
catch (ActivitiOptimisticLockingException | DeadlockLoserDataAccessException e)
{
// 等待后重试
Thread.sleep(100);
}
}
}
bug怎么这么多!