☰
Flowable 6.7.2数据库建表脚本拆解与MySQL/Oracle执行指南
2026/10/12 14:55:52 网站建设 项目流程

简介:Flowable 6.7.2数据库建表SQL脚本,面向使用该工作流引擎的开发者与运维人员,解决MySQL和Oracle环境下初始化数据库结构的实际需求。压缩包共2个SQL文件,整体大小仅17KB,分别提供MySQL与Oracle全量建表语句,可直接在对应数据库执行。脚本覆盖流程定义表、运行时表、历史表、变量表、事件表及辅助表六大类,完整呈现Flowable核心数据模型。已有1833人学习使用,适合快速部署Flowable、理解其流程运转机制或进行二次开发的读者。借助这套脚本,可快速完成数据库层准备,减少手动建表成本,同时为后续流程定义导入和任务管理奠定基础。无论是搭建演示环境,还是排查持久化异常,这套表结构脚本都能提供清晰参考。

1. flowable-6.7.2 建表脚本到底是什么:一个 zip 解决两套数据库的初始化

做工作流集成时,最容易被低估的就是数据库初始化这一步。很多人以为把 flowable-6.7.2 的 jar 包丢进项目、启动应用,引擎就会自动把表建好,结果要么是日志里刷出一大片建表异常,要么是表建了一半、外键挂不上,连流程部署都走不到。而当你决定从官方仓库拿完整的建表 SQL 时,会发现它不是一个 .sql 文件,而是一个 zip,里面同时装了 MySQL 和 Oracle 两套脚本——这就是这个 zip 的核心价值:一套资源,覆盖两个主流数据库方言,不需要去网上找零散的、可能已经被人改过的单库脚本。这篇文章会把这套脚本拆开讲清楚,从目录结构、执行顺序、两库差异,到真正执行时的参数调整和踩坑记录,帮你一次把库建对。

2. 先看懂脚本再执行:目录结构、建表逻辑与引擎自动建表的边界

拿到 zip 之后急着解压执行,是第一个翻车点。Flowable 的建表脚本不是单一文件,而是按模块拆分的多个 SQL,顺序错了、选错版本了,都会导致外键约束缺失或者表关联不上。这一章先讲清楚 zip 内部的组织方式,再讲它和引擎自动建表之间的关系。

2.1 脚本目录里到底有什么:create、drop 与 quartz 三套文件

解压后能看到两套顶层目录,一般按数据库类型区分,下面各自有 create 和 drop 两个子目录。create 目录里是建表语句,drop 目录里是对应的删表语句。实际项目里 drop 脚本用得少,但做自动化测试环境重建时很管用。

create 目录下的文件并不是一张表一个文件,而是按模块聚合的。常见的有flowable.identity、flowable.common、flowable.variable、flowable.event、flowable.entity、flowable.job、flowable.task、flowable.cmmn、flowable.dmn、flowable.app等。此外还有一套带quartz前缀的文件,对应 Flowable 的任务调度表。如果你用了 Flowable 自带的定时任务能力,也就是 job 模块依赖 Quartz 做分布式调度,那么这些 quartz 表必须建;如果完全不用定时任务,或者用 Spring 自带调度替代,就可以跳过。

# 解压后的大致结构(以常见官方包结构为例) flowable-6.7.2-sql/ ├── create/ │ ├── flowable.identity.sql │ ├── flowable.common.sql │ ├── flowable.variable.sql │ ├── flowable.event.sql │ ├── flowable.entity.sql │ ├── flowable.job.sql │ ├── flowable.task.sql │ ├── flowable.cmmn.sql │ ├── flowable.dmn.sql │ ├── flowable.app.sql │ └── quartz/ │ └── quartz.tables.sql └── drop/ ├── flowable.drop.sql └── quartz/ └── quartz.drop.sql

注意文件名的模块顺序并不是严格等价的。identity 和 common 是基础表,entity 和 variable 依赖它们,task 和 job 又依赖 entity。手工逐个执行时,按这个顺序来最安全。另外提醒一句,不同发行渠道的 zip 内部文件名可能略有差异,比如有的把 create 和 drop 合并到一个文件中,但模块拆分逻辑是一致的,认准ACT_前缀的表名就不会跑偏。

2.2 引擎自动建表与手动执行脚本:谁先谁后

Flowable 引擎在启动时有一个database-schema-update配置项,默认值是true,含义是如果没有表就自动创建。很多人因此认为手动建表没必要,但实际项目中我一般不建议依赖自动建表,原因有两个。

第一,自动建表用的 DDL 来自引擎内部编译好的资源,它不会帮你区分 MySQL 和 Oracle 的方言之外的数据库配置差异,比如字符集、表空间、字段长度,这些都得靠数据库侧预设,出问题后排查链路很长。第二,不同模块的表由不同引擎组件管理,如果应用启动顺序和模块初始化顺序不一致,偶发性的先建后建问题会出现,比如外键表先建、主键表后建,虽然数据库不会炸,但日志里会刷出无法忽略的警告。

所以我的做法是:手动执行 zip 里的 SQL 来建表,然后把database-schema-update改成false,让引擎不再干预 DDL。这样既能保证表结构完全可控,又能保留引擎对表结构版本的校验能力——它启动时会检查现有表与自身期望的版本是否匹配,不匹配就直接报错,能提前暴露脚本版本选错的问题。如果某个模块表缺失,引擎也会给出明确提示,定位比自动建表快得多。

3. MySQL 与 Oracle 建表脚本的差异:类型映射、索引长度与字符集

同一套流程引擎,两套 SQL,差异集中在数据库方言上。MySQL 与 Oracle 在数据类型、索引能力、字符集处理上差异明显,Flowable 针对两个版本做了不同处理。执行前不搞清楚这些差异,就会出现"MySQL 没问题 Oracle 建一半失败"这种双库项目里常见的问题。

3.1 核心表的建表思路:ACT_GE、ACT_RU、ACT_HI 三大分类

Flowable 的表以ACT_前缀开头,按用途分几个大类。ACT_GE_是通用数据,比如ACT_GE_BYTEARRAY存流程定义的二进制资源,ACT_GE_PROPERTY存引擎内部属性表,它的作用相当于版本元数据存储。ACT_RU_是运行时数据,RU表示 Runtime,流程实例、任务、变量、作业都在这里,流程结束后这些表的记录通常会被清理。ACT_HI_是历史数据,HI表示 History,所有跨流程实例的历史信息都在,包括已办、历史变量、历史活动节点。

建表脚本的核心逻辑就是按这三个维度拆分存储,让运行时表保持轻量,历史表承担查询压力。这带来的实践影响是:如果你们公司对已办列表的历史数据有多年归档要求,关注的重点应该在ACT_HI_系列表的索引设计上,而不要轻易改动ACT_RU_表的结构。

3.2 MySQL 版脚本的三个必调参数

MySQL 版本建表语句里,每个表基本都是CREATE TABLE IF NOT EXISTS,而且明确指定了ENGINE=InnoDB和DEFAULT CHARSET。默认字符集通常跟随主库配置,但有两个参数我建议执行前直接确认。

第一个是utf8mb4与utf8的选择。Flowable 6.7.2 的脚本里有不少VARCHAR(255)甚至更长的字段,如果建表字符集是utf8,而应用连接字符串里配置了characterEncoding=utf8mb4,流程变量里放入 emoji 字符时就会报编码错误。实际项目里字符集在数据库初始化时已经定好,单独为几张表改成utf8mb4又会导致 join 两表字符集不一致,索引失效。所以看脚本时,重点是确认它用的是不是DEFAULT CHARSET且不硬编码,推荐让每张表都继承库级字符集,不要单独指定utf8。

第二个是ROW_FORMAT。MySQL 5.7 默认是DYNAMIC,8.0 默认也是,但如果你们的库从 5.6 迁移过来,表的行格式可能是COMPACT。COMPACT行格式下,VARCHAR(255)配合utf8mb4时,单列索引长度容易接近上限,报错的典型信息是Specified key was too long; max key length is 767 bytes。脚本本身不会管这个,你得在库级别先确认。

第三个是大小写敏感配置lower_case_table_names。在 Linux 上默认值是 0,表名区分大小写,而 Flowable 的表名是统一的ACT_GE_...大写形式;Windows 和 macOS 上默认值是 1,不区分大小写。如果一个团队有人在 Windows 开发、生产在 Linux,脚本执行没问题,但后续代码里如果出现小写表名,开发环境正常、生产环境报Table doesn't exist,这类问题最难查。

3.3 Oracle 版脚本与 MySQL 的五个关键差异

Oracle 版本的脚本里看不到ENGINE和CHARSET这类 MySQL 特有语法,取而代之的是表空间、VARCHAR2、以及明确的约束命名方式。具体执行时有五个差异点需要格外注意。

一是 Oracle 没有AUTO_INCREMENT或IDENTITY,Flowable 的主键靠序列(Sequence)或者应用层 UUID 生成,所以脚本里和相关配套会一起出现序列创建语句,执行建表脚本时,这些序列语句必须一起执行,漏掉会导致新增数据时主键冲突。

二是VARCHAR2的长度单位。Oracle 默认按字节计,VARCHAR2(255)在AL32UTF8字符集下最多存 85 个汉字。Flowable 的脚本在设计时已考虑了这个限制,字段长度取值一般偏保守,但你往表里手工插入数据做实验时,如果发现中文插不进去,优先确认数据库的NLS_LENGTH_SEMANTICS是不是BYTE。

三是索引长度限制。Oracle 的索引条目总长度有上限,脚本里对带索引的大字段用的是VARCHAR2(512)甚至更短,和 MySQL 的VARCHAR(255)设计风格不太一样,这在执行时不需要干预,但要理解为什么两套脚本的字段长度不同——不是写错了,是方言限制不同。

四是空字符串与NULL的区别。Oracle 里空字符串等于NULL,Flowable 的查询逻辑如果对这两者区分,在 Oracle 下行为会不一样。好在脚本层面不需要解决这个,只是提醒你,后续做数据迁移时不要试图把两库数据直接同步。

五是方案(Schema)归属。Oracle 实例里一个用户对应一个 Schema,执行建表脚本时,当前连接用户是谁,表就建在哪个 Schema 下。很多人习惯用 system 或 sys 账号执行业务脚本,结果表建到了系统 Schema 下,业务账号查询时找不到表。正确的做法是创建专用业务账号,用它登录执行脚本,后续应用连接也用这个账号。

4. 在 MySQL 和 Oracle 上执行建表脚本:完整步骤与验证

这一章直接进入操作。目标是让读者在十分钟内把两套库的表都建好,并且能确认建表结果没问题。建议准备一个纯净的测试库,不要用生产库试。

4.1 MySQL 执行步骤与最小验证命令

先把 zip 解压,然后确认连接信息,包括库名、账号、字符集。建议在连接串里显式指定characterEncoding和useSSL,否则建表本身没问题,后续应用连上来时容易产生额外告警。

mysql -h 127.0.0.1 -P 3306 -u flowable_user -p flowable_db \ --default-character-set=utf8mb4 \ -e "source /path/to/create/flowable.identity.sql"

这里只演示了单文件执行,逐个文件执行时重复该命令即可,注意每个文件单独执行比一次source多个文件更容易定位出错位置。default-character-set=utf8mb4只影响客户端传输字符集,不会改变表定义里的字符集,表结构字符集取的是数据库默认值。

执行完成后,验证表数量和关键表:

USE flowable_db; SHOW TABLES LIKE 'ACT\_%'; SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'flowable_db' AND table_name LIKE 'ACT\_%';

第一条命令看表名清单,第二条看总数。验证的重点是ACT_GE_PROPERTY这张表里有没有数据,它是引擎版本校验表,如果没有初始化数据,说明对应模块的脚本没有执行成功。

SELECT * FROM ACT_GE_PROPERTY;

正常会看到几条记录,字段值是版本号之类的内容。如果这张表是空的,后续启动引擎时它会尝试重建,大概率报结构冲突。

4.2 Oracle 执行步骤与最小验证命令

Oracle 这边可以用 sqlplus 或者 SQL Developer。sqlplus 在服务端安装目录里自带,脚本执行前注意当前连接的 Schema 必须是业务账号。

sqlplus flowable_user/your_password@127.0.0.1:1521/ORCLPDB1 \ @/path/to/create/flowable.identity.sql

Oracle 的 sqlplus 默认会输出大量的Table created和Sequence created信息,看到一部分报错不要慌,先确认是不是外键约束依赖顺序问题。很多 Oracle 版脚本不会严格按依赖顺序排列,中间穿插几个ORA-00942: table or view does not exist很常见,只要后续表建成功时把前面缺的表补齐即可。但要注意,如果报错的语句是ALTER TABLE ADD CONSTRAINT,说明外键关联的表当时不存在,这种必须在全部表建完之后重新执行一次约束语句,否则外键缺失,引擎启动时不报错,数据清理时出问题。

验证方式和对 MySQL 风格不同,Oracle 用数据字典视图:

SELECT table_name FROM user_tables WHERE table_name LIKE 'ACT\_%' ESCAPE '\' ORDER BY table_name;

user_tables只显示当前 Schema 下的表,比查all_tables更干净。同样检查ACT_GE_PROPERTY的记录数。

SELECT * FROM ACT_GE_PROPERTY;

另外多一步引擎元数据序列的确认。Oracle 版脚本在创建表的同时会创建多个ACT_*_SEQ序列,如果序列缺失,插入数据时主键冲突报错,启动阶段不会暴露。检查序列用USER_SEQUENCES。

SELECT sequence_name FROM user_sequences WHERE sequence_name LIKE 'ACT\_%' ESCAPE '\';

我在实际项目里吃过这个亏。某次 Oracle 环境迁移,只同步了表数据没同步序列,结果应用启动正常,但一人发起流程就报主键冲突,排查了很久才定位到是序列没建。

5. 建表脚本执行避坑:从日志报错到数据可用性,五个真实翻车点

这一章把执行脚本过程中高概率遇到的坑整理成清单。每条都按现象、原因、解决的路径来写,方便直接对照排查。

5.1 现象:MySQL 报Specified key was too long; max key length is 767 bytes

建表脚本执行到某一张表时,报索引长度超限。原因通常是 MySQL 5.6 或 5.7 早期版本,innodb_large_prefix参数未开启,或者表行格式为COMPACT。VARCHAR(255)加上utf8mb4的 4 字节编码,单列索引长度达到 1020 字节,超出了限制。

解决方式有两种。优先改数据库参数,开启innodb_large_prefix并设置innodb_file_format = Barracuda,同时把表的行格式改为DYNAMIC。如果数据库版本是 5.7 之后,默认已开启,问题不太会出现。若数据库是由 DBA 统一管理的,不允许单独开参数,那就只能把相关字段长度缩短,注意这里不能直接改脚本里所有VARCHAR,需要对照索引覆盖情况,单独改有问题的那几张表。

5.2 现象:表建好了,但中文注释和流程变量显示乱码

建表成功、应用也正常,但通过管理界面查看流程名称时中文是乱码。原因分两层。第一层是建表时字符集不对,表实际用了latin1;第二层是应用连接串字符集不对,characterEncoding没有设置或者是utf8,与表字符集不一致。

解决方式:先查表字符集确认第一层。SHOW TABLE STATUS LIKE 'ACT_RU_TASK',看Collation字段。如果是latin1_swedish_ci,说明建表时库的默认字符集本身就不是 utf8mb4。处理办法是重建这几张表,建表前先ALTER DATABASE ... CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,再重新执行脚本。应用侧连接串则统一写成characterEncoding=utf8mb4。不要想着在脚本里给每张表追加DEFAULT CHARSET=utf8mb4,一旦后续新增表漏配,这类问题会再犯。

5.3 现象:Oracle 下大量ORA-01950: no privileges on tablespace

执行脚本时,前几张表建成功,中间开始出现大量表空间权限报错。原因是没有给业务账号分配默认表空间的配额。用 system 账号建了一个业务账号,但只给了CONNECT和RESOURCE角色,RESOURCE角色默认不会自动分配表空间配额。

解决方式:用 DBA 账号执行授权,把业务账号的默认表空间和临时表空间指定好,并给予无限配额。

ALTER USER flowable_user QUOTA UNLIMITED ON USERS; ALTER USER flowable_user DEFAULT TABLESPACE USERS; ALTER USER flowable_user TEMPORARY TABLESPACE TEMP;

如果公司 DBA 不允许无限配额,可以指定一个固定大小,例如 500M 或 1G,以实际业务量评估。流程引擎的表包括历史数据,涨得比普通业务表快,配额给得太小半年后就要扩容。

5.4 现象:应用启动后访问流程接口返回 404,日志提示找不到表

这个现象比较隐蔽。应用能启动,部分接口能访问,但点击某个流程相关操作时报错,提示某张ACT_RU_*表不存在。原因通常是执行脚本时用了大写表名,但 MySQL 的lower_case_table_names=1环境里所有表被存成小写,而代码里查询语句使用的是大写,或者反过来。Linux 生产环境lower_case_table_names=0,表名严格区分大小写,而在开发机上用大小写不敏感的方式建的表,导出的 SQL 文件里表名变成了小写,带到生产一执行,就出现大小写不一致。

解决方式:在目标机器上先确认lower_case_table_names的值,然后保证建表脚本中的表名大小写与代码侧一致。最优做法是统一采用脚本里的大写表名,并把各环境的lower_case_table_names配成一致。这个参数比较特殊,修改后需要重启 MySQL 且会影响已有表的大小写,所以要在初始化前就定好,没有后悔药可吃。

5.5 现象:外键约束重复执行报错,或者建表时外键缺失

手动执行多个脚本文件时,如果两次执行同一个flowable.entity.sql,第二次会报重复;但如果第一个文件执行到一半失败中止,依赖它的表可能建好了、外键没建上。原因就是脚本文件和脚本文件之间没有事务保护,DDL 在 MySQL 里大部分操作不可回滚。

解决方式:执行前确认没有残留表。最简单的方法是先执行flowable.drop.sql,保证库是干净的,然后重新按顺序执行 create 脚本。在 Oracle 上更稳妥的做法是先跑@flowable.drop.sql,再开始建。注意 drop 脚本的执行顺序和 create 相反,直接source整个文件时不需要额外关注,脚本内部已经编排好了。如果不想重复执行这些步骤,也可以在每个 sql 文件前手动确认输出日志中没有ERROR关键字,再执行下一个文件。

6. 进阶验证:用一条查询确认表与序列完全就绪,并给后续升级留后路

前面的步骤做完,库能用了,但作为负责任的一线开发者,我习惯再做一次彻底验证,确认建表脚本执行得完整,而不仅仅是"能启动"。这一步能帮你提前发现那些不致命但后续会拖累排查效率的隐患。

先看 MySQL。整个流程引擎如果包含流程、任务、CMMN、DMN、表单、内容引擎这些模块,建完的表会涵盖ACT_RE_、ACT_RU_、ACT_HI_、ACT_GE_、ACT_ID_、ACT_EVT_、ACT_FO_、ACT_CO_、ACT_CMMN_、ACT_DMN_、ACT_APP_这些前缀。要确认基础引擎建对了,重点查一组"骨架表":

SELECT table_name, table_comment FROM information_schema.tables WHERE table_schema = 'flowable_db' AND table_name IN ( 'ACT_GE_PROPERTY', 'ACT_GE_BYTEARRAY', 'ACT_RE_DEPLOYMENT', 'ACT_RE_PROCDEF', 'ACT_RU_EXECUTION', 'ACT_RU_TASK', 'ACT_RU_VARIABLE', 'ACT_HI_PROCINST', 'ACT_HI_TASKINST', 'ACT_HI_VARINST' );

这十张表是流程引擎最小可用集合。如果全在,说明核心建表成功;如果有缺失,先不要启动引擎,回去跑对应的模块脚本。

Oracle 侧的验证要分两步。第一步查表,第二步查序列。序列在导入表数据时不会自动恢复,人工补的话要确认当前值和表已有数据的最大主键是对齐的,这一步容易做漏。

接下来是给升级留后路的问题。脚本执行完,数据库建表只是开始,后续升级通常用 Flyway 或 Liquibase 这类迁移工具管理增量脚本。6.7.2 这个版本号的递增路径你们团队自己掌握,我不在这里指定具体的升级版本,但可以建议你们把手动执行过的这套脚本纳入版本控制,并且每个环境都记录执行时间和执行人的信息。

具体做法是建一张表专门记录已经执行过的脚本文件。很多人觉得这个动作多余,但当你经历过一次"测试环境正常、生产环境少执行了某个模块脚本,导致上线后接口报错"的场面,就会理解这个记录的价值。建表和数据插入代码可以参考下面这样:

CREATE TABLE IF NOT EXISTS flowable_script_log ( id INT PRIMARY KEY AUTO_INCREMENT, file_name VARCHAR(255) NOT NULL, db_type VARCHAR(32) NOT NULL, execute_time DATETIME NOT NULL, checksum VARCHAR(64) NOT NULL, UNIQUE KEY uk_script (file_name, db_type) );
INSERT INTO flowable_script_log (file_name, db_type, execute_time, checksum) VALUES ('flowable.identity.sql', 'mysql', NOW(), SHA2('flowable.identity.sql', 256));

每次执行完一个 SQL 文件就插入一条记录,用file_name加db_type做唯一键。这样任何环境缺少哪个脚本,一条LEFT JOIN就能查出来。我个人的习惯是把这个表和项目代码一起维护,数据库结构变更时它作为第一份参考文档存在,比安排同事维护一份文本说明可靠得多——人记不住细节,表格能。

最后还想提一个容易被忽略的小习惯:不要把建表脚本放到应用启动时自动执行。之前为了省事,我曾尝试在应用启动时判断表是否存在、不存在则调用ScriptRunner执行 SQL 文件,当时看确实便利,后续引入集群部署时立刻出了问题——多个实例同时启动会并发执行 DDL,MySQL 直接报重复键错误,引发启动失败。在那之后我就恢复为一次性初始化、版本管理、团队共享记录的三步走。希望这个坑能帮到你,也祝你的 Flowable 项目在库表这一关走得顺畅。

本文还有配套的精品资源,点击获取

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

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

立即咨询