Activiti7数据库表结构全解析:从25张表看懂工作流引擎的运行逻辑
2026/6/23 5:07:29 网站建设 项目流程

Activiti7数据库表结构全解析:从25张表看懂工作流引擎的运行逻辑

第一次接触Activiti7时,最让我困惑的不是BPMN流程图设计,而是启动项目后自动生成的那25张数据库表。这些以act_开头的表究竟存储了什么?为什么有的表在流程结束后数据会消失?本文将用真实的请假流程案例,带您穿透代码层直达数据库,理解工作流引擎的底层运行机制。

1. 核心表分类与设计哲学

Activiti7的表结构设计遵循运行时效率历史追溯分离的原则。所有表名采用前缀+功能的分段命名方式:

-- 表名通用模式 act_[前缀]_[功能描述]

1.1 三大核心表群

前缀全称数据生命周期典型表举例
RERepository永久存储ACT_RE_DEPLOYMENT
RURuntime流程实例存活期间ACT_RU_TASK
HIHistory永久存储ACT_HI_PROCINST

RE表群就像流程定义的"保险柜",存储着:

  • 部署的BPMN文件二进制内容(ACT_GE_BYTEARRAY)
  • 流程定义元数据(ACT_RE_PROCDEF)

RU表群则是工作流的"运行时内存",包含:

  • 正在执行的任务(ACT_RU_TASK)
  • 流程变量(ACT_RU_VARIABLE)
  • 当前执行路径(ACT_RU_EXECUTION)

HI表群如同"黑匣子记录仪",忠实记录:

  • 已完成的流程实例(ACT_HI_PROCINST)
  • 所有活动节点历史(ACT_HI_ACTINST)
  • 任务处理人变更(ACT_HI_IDENTITYLINK)

提示:RU表的数据会在流程实例结束后自动清除,这是设计上的性能优化,避免运行表无限膨胀。

2. 流程部署的数据库足迹

当执行repositoryService.createDeployment()时,数据库会发生这些变化:

// 典型部署代码示例 Deployment deployment = repositoryService.createDeployment() .addClasspathResource("leave-request.bpmn20.xml") .name("请假流程V2") .deploy();

2.1 ACT_RE_DEPLOYMENT表

ID_NAME_DEPLOY_TIME_
2501请假流程V22023-08-20 14:30:22

这个表记录每次部署的元信息,其主键会关联到多个其他表。

2.2 ACT_GE_BYTEARRAY表

ID_DEPLOYMENT_ID_NAME_BYTES_
50012501leave-request.bpmn[BLOB数据]
50022501leave-request.png[BLOB数据]

存储的是流程定义的原始文件,包括:

  • BPMN 2.0 XML文件
  • 流程图形化渲染图片

2.3 ACT_RE_PROCDEF表

ID_KEY_VERSION_DEPLOYMENT_ID_RESOURCE_NAME_
leave:1:2501leave12501leave-request.bpmn

关键字段解析:

  • ID_=KEY_:VERSION_:DEPLOYMENT_ID_
  • KEY_对应BPMN文件中的process id属性
  • VERSION_自动递增,相同KEY的流程会版本升级

3. 流程实例运行时的数据流动

以请假流程为例,当员工发起申请时:

ProcessInstance instance = runtimeService .startProcessInstanceByKey("leave");

3.1 ACT_RU_EXECUTION表变化

ID_PROC_INST_ID_PROC_DEF_ID_ACT_ID_IS_ACTIVE_
30013001leave:1:2501start0
30023001leave:1:2501apply1

这个表保存流程的执行上下文,重要字段:

  • PROC_INST_ID_:流程实例唯一标识
  • ACT_ID_:当前所处的BPMN节点ID
  • IS_ACTIVE_:0表示已完成的执行分支

3.2 ACT_RU_TASK表生成

ID_PROC_INST_ID_NAME_TASK_DEF_KEY_ASSIGNEE_
40013001提交请假单applyzhangsan

此时前端展示给用户的任务列表,就是查询此表:

SELECT * FROM ACT_RU_TASK WHERE ASSIGNEE_ = 'zhangsan'

3.3 历史表的初始记录

ACT_HI_PROCINST表会立即生成记录:

ID_PROC_DEF_ID_START_TIME_START_USER_ID_
3001leave:1:25012023-08-20 15:00:00zhangsan

4. 任务处理引发的连锁反应

当张三完成任务时:

taskService.complete(taskId);

4.1 运行时数据迁移

ACT_RU_TASK表

  • 删除张三的当前任务记录
  • 插入李四的新审批任务记录

ACT_RU_VARIABLE表(如果有流程变量):

ID_TYPE_NAME_EXECUTION_ID_TEXT_VALUE_
6001stringreason3002年假申请

4.2 历史表的双重记录

ACT_HI_TASKINST表记录任务详情:

ID_PROC_DEF_ID_TASK_DEF_KEY_START_TIME_END_TIME_
4001leave:1:2501apply2023-08-20 15:00:002023-08-20 15:05:00

ACT_HI_ACTINST表记录所有活动节点:

ID_PROC_DEF_ID_ACT_ID_ACT_TYPE_START_TIME_END_TIME_
7001leave:1:2501startstartEvent2023-08-20 15:00:002023-08-20 15:00:02
7002leave:1:2501applyuserTask2023-08-20 15:00:022023-08-20 15:05:00

5. 高级应用与性能优化

5.1 历史级别配置

activiti.cfg.xml中可以调整历史记录粒度:

<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="history" value="audit" /> </bean>

可选值:

  • none:不记录历史
  • activity:仅记录节点(默认)
  • audit:记录节点与变量
  • full:完整记录(含表单提交细节)

5.2 常见查询优化方案

场景1:快速查找用户的待办任务

-- 低效写法 SELECT * FROM ACT_RU_TASK WHERE ASSIGNEE_ = 'zhangsan'; -- 优化方案:添加组合索引 CREATE INDEX idx_ru_task_assignee ON ACT_RU_TASK(ASSIGNEE_);

场景2:统计流程平均耗时

-- 使用历史视图 SELECT AVG(DATEDIFF(END_TIME_, START_TIME_)) FROM ACT_HI_PROCINST WHERE END_TIME_ IS NOT NULL;

5.3 自定义表前缀

对于多租户系统,可以修改表名前缀:

ProcessEngineConfiguration config = new StandaloneProcessEngineConfiguration() .setDatabaseSchemaUpdate("true") .setDatabaseTablePrefix("CUST_");

6. 实战:诊断数据不一致问题

曾遇到一个生产环境问题:流程实例显示已完成,但任务列表仍有残留任务。通过以下步骤排查:

  1. 检查运行时表

    SELECT * FROM ACT_RU_EXECUTION WHERE PROC_INST_ID_ = '3001';

    发现存在IS_ACTIVE_=1的异常记录

  2. 对比历史表

    SELECT * FROM ACT_HI_PROCINST WHERE ID_ = '3001';

    显示流程已结束

  3. 解决方案

    runtimeService.deleteProcessInstance("3001", "数据修复");

这种数据不一致通常是由于系统异常终止导致的,关键是要建立RU表与HI表的交叉验证机制。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询