activiti工作流发起流程时出现事务冲突的优化方案

【问题】

由于bpm流程是通过监听策略进行触发执行一些操作(如审核通过、不通过、取消等),导致数据库查询、修改同时对一个表操作,导致流程发起失败等情况。

【方案】

  1. 优化数据库设计

    1.1 索引优化
    确保流程实例ID(PROC_INST_ID_)、任务ID(TASK_ID_)、执行ID(EXECUTION_ID_)等高频查询字段建立索引,减少锁竞争。

    1.2 避免全表扫描
    通过EXPLAIN分析慢查询,优化涉及ACT_RU_TASK、ACT_RU_EXECUTION等运行时表的SQL。

  2. 避免长事务

    拆分业务逻辑,将非核心操作(如日志、通知)移出事务:

    @Transactional
    public void startProcess()
     {
        // 1. 启动流程(短事务)
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("approval");
        
        // 2. 异步处理耗时操作
        asyncService.sendNotification(instance.getId()); // 非事务方法
    }
  1. 锁顺序控制

    统一资源操作顺序,若需更新多个流程实例,按ID排序后操作,避免交叉锁引发死锁。

    List<String> instanceIds = Arrays.asList("id1", "id2", "id3");
    Collections.sort(instanceIds); // 强制排序

    instanceIds.forEach(id -> {
        runtimeService.setVariable(id, "status", "approved");
    });
  1. 重试机制

    捕获死锁异常并重试方案

    public void safeStartProcess() 
    {
        int retries = 3;
        while (retries-- > 0) 
        {
           try 
           {
                runtimeService.startProcessInstanceByKey("approval");
                break;
            } 
            catch (ActivitiOptimisticLockingException | DeadlockLoserDataAccessException e) 
            {
                // 等待后重试
                Thread.sleep(100); 
            }
        }
    }
posted @ 2025-08-14 10:15  clya  阅读(23)  评论(0)    收藏  举报