ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Flowable 6.7.2 建表脚本实战:MySQL与Oracle表空间及执行顺序详解

Flowable 6.7.2 建表脚本实战:MySQL与Oracle表空间及执行顺序详解 简介这份压缩包专为Flowable 6.7.2工作流引擎的数据库初始化准备同时覆盖MySQL与Oracle两种主流数据库解决开发者初次部署时不知如何建表、表结构不一致的问题。压缩包内含2个SQL脚本大小仅17KB分别针对MySQL和Oracle编写脚本按功能模块组织包含ACT_RE_*流程定义、ACT_RU_*运行时任务与执行实例、ACT_HI_*历史记录、ACT_RU_VARIABLE流程变量、ACT_RU_EVENT_SUBSCR事件订阅以及ACT_GE_*通用二进制数据等核心建表语句执行后即可获得Flowable运行所需的完整数据表结构。目前已有1826人学习适合需要快速搭建Flowable开发环境、或希望深入理解其底层表模型的Java工程师与运维人员。借助这两份脚本读者不仅能一次性完成MySQL或Oracle环境的初始化还能通过对比两套SQL直观掌握不同数据库在字段类型、索引和约束上的处理差异为后续流程实例管理、历史数据查询和二次开发提供可靠基础。 Flowable 6.7.2 的数据库脚本拿到手第一步该干什么我见过不少同事解压完 zip 直接一股脑往数据库里执行结果 MySQL 还好Oracle 那边先是报错 ORA-00922接着又是表空间不存在折腾半天才发现脚本里默认表空间根本就没建。这篇就把 Flowable 6.7.2 的 MySQL 和 Oracle 建表脚本从头到尾盘一遍包括脚本结构、执行顺序、表空间处理、字符集坑点以及我实际踩过的问题给你一条能直接照做的路径。1. 项目核心场景与脚本文件结构1.1 Flowable 6.7.2 是什么这套脚本解决什么问题Flowable 是目前 Java 生态里用得最广的开源工作流引擎之一从 Activiti 5 分叉出来之后独立发展6.7.2 算是 6.x 系列里很稳定的一个版本。它核心解决的是业务流程建模、部署、执行、审批流转这一类问题开发者在 Spring Boot 项目里引入 flowable-spring-boot-starter 后引擎运行起来会自动检查数据库里有没有 ACT_ 开头的表如果没有就会尝试自动建表。自动建表看起来方便但生产环境基本不会这么干。原因很直接自动建表用的连接账号通常需要较高的 DDL 权限而生产库的账号往往只给了 DML 权限另外自动建表过程不可控表空间、字符集、索引分区这些都没法按项目规范来定制。所以官方提供了手工建表的脚本也就是你拿到的这套 flowable-6.7.2 数据库脚本在应用部署之前先把表结构准备好。这套 zip 里常见的文件组织方式一般是这样的flowable.mysql.create.engine.sql引擎核心表包含流程定义、流程实例、任务、执行实例等flowable.mysql.create.history.sql历史数据表流程实例结束后的归档数据落在这里flowable.mysql.create.identitylink.sql身份关联表处理用户与任务的关联关系flowable.mysql.create.common.sql通用表比如属性配置表flowable.mysql.create.entitylink.sql实体关联表flowable.mysql.create.eventsubscription.sql事件订阅表flowable.mysql.create.job.sql定时任务相关表Oracle 对应的是flowable.oracle.create.*.sql文件名规则一致。另外还有drop系列的脚本用于删除表一般在彻底重建环境时才用。1.2 脚本文件的执行顺序与依赖关系这套脚本不是乱序执行而是有明确的依赖关系。我的经验是严格按照官方readme里列出的顺序来flowable.mysql.create.common.sql先建通用表flowable.mysql.create.identitylink.sqlflowable.mysql.create.entitylink.sqlflowable.mysql.create.eventsubscription.sqlflowable.mysql.create.engine.sqlflowable.mysql.create.job.sqlflowable.mysql.create.history.sql为什么这个顺序重要因为引擎表engine里的外键会引用 identitylink、entitylink 这些表如果先建 engine 表再建 identitylink 表MySQL 下 InnoDB 引擎在创建外键约束时会直接报错。Oracle 也有同样的问题。所以不按顺序来后面就是一堆外键错误。还有一点要注意通用表common里的ACT_GE_PROPERTY表里面存了 Flowable 的 schema 版本号schema.version字段。引擎启动时会检查这个版本号是否与依赖的 Flowable 版本一致不一致会直接抛异常。所以如果手上是 6.7.2 的引擎就必须用 6.7.2 配套的建表脚本混用版本会出问题。2. MySQL 与 Oracle 建表脚本的关键差异2.1 数据类型和默认值处理的区别MySQL 和 Oracle 的脚本差异核心在于数据类型的映射。MySQL 里 Flowable 的字段大量使用varchar、datetime(6)、longtext这类类型。比如CREATE TABLE ACT_RU_TASK ( ID_ varchar(64) NOT NULL, REV_ int, NAME_ varchar(255), CREATE_TIME_ datetime(6), ... PRIMARY KEY (ID_) )这里datetime(6)是 MySQL 6 位微秒精度的时间类型Flowable 在记录任务创建时间、截止时间时会用到毫秒级精度。而在 Oracle 里对应的是TIMESTAMP(6)CREATE TABLE ACT_RU_TASK ( ID_ NVARCHAR2(64) NOT NULL, REV_ NUMBER(10), NAME_ NVARCHAR2(255), CREATE_TIME_ TIMESTAMP(6), ... PRIMARY KEY (ID_) )Oracle 脚本里大量采用NVARCHAR2这是为了避免字符集问题。如果数据库字符集是AL32UTF8VARCHAR2也能存中文但NVARCHAR2用的是国家字符集在跨字符集场景下更稳定。MySQL 那边如果表字符集设置正确utf8mb4varchar存中文没有任何问题。字段默认值方面MySQL 可以很随意地写DEFAULT NULLOracle 的脚本则基本不写默认值因为 Flowable 引擎层会自己管理字段的赋值数据库层的默认值反而可能干扰。比如REV_这个版本号字段MySQL 下可能写了DEFAULT 0Oracle 下就直接NUMBER(10)不写默认值。2.2 主键生成方式自增与序列这个问题是 MySQL 转 Oracle 最常踩的坑。MySQL 的 Flowable 表主键都是varchar(64)用 UUID 字符串。引擎在 Java 层用UUID.randomUUID().toString().replace(-, )生成 32 位字符串所以主键本身不需要数据库自增。但 Oracle 那边同样用NVARCHAR2(64)做主键也不依赖序列。也就是说Flowable 设计上就规避了不同数据库主键策略差异的问题统一用应用层 UUID。这一点和 Activiti 5 时代用自增主键完全不同也是 Flowable 能同时支持这么多数据库的原因之一。不过 Oracle 脚本里有DROP SEQUENCE和CREATE SEQUENCE的语句。这是给某些特定表的批量插入场景用的比如ACT_RU_JOB里可能会有通过 Oracle Sequence 生成数字编号的写入逻辑。这套序列在 Oracle 脚本里会创建但如果你完全不走引擎的批量逻辑手动插入数据时用不到也不用管。2.3 Oracle 表空间处理Oracle 脚本顶部一般会有类似的语句或者至少注释中会提到表空间CREATE TABLE ACT_GE_PROPERTY ( NAME_ NVARCHAR2(64) NOT NULL, VALUE_ NVARCHAR2(300), REV_ NUMBER(10), PRIMARY KEY (NAME_) ) TABLESPACE FLOWABLE;这里TABLESPACE FLOWABLE就是个隐藏坑。如果你的数据库实例里没有FLOWABLE这个表空间执行会直接报ORA-00959: tablespace FLOWABLE does not exist。很多第一次接触的人以为是自己脚本执行姿势不对其实就是表空间没建。解决方式有两种直接在脚本里把TABLESPACE FLOWABLE替换成你项目实际的表空间名或者干脆去掉这行提前执行建表空间语句如果要建表空间比较稳的做法是CREATE TABLESPACE FLOWABLE DATAFILE /u01/app/oracle/oradata/ORCL/flowable01.dbf SIZE 1G AUTOEXTEND ON NEXT 100M MAXSIZE 10G;注意数据文件路径要根据实际 Oracle 环境调整。我的建议是如果 Flowable 表要放进统一的应用表空间直接全局替换掉脚本里的TABLESPACE FLOWABLE字符串比单独建一个表空间更省事也方便后续备份恢复。3. 建表实操从解压到执行成功的完整过程3.1 MySQL 环境下的建表全过程准备环境之前先把 MySQL 版本确认一下。Flowable 6.7.2 官方对 MySQL 的要求是 5.7 及以上建议 8.0。MySQL 8.0 的默认字符集是utf8mb4存储中文和多字节字符都没有问题Flowable 的字符串字段长度也够用。第一步创建数据库并明确字符集和排序规则。CREATE DATABASE flowable CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;这里我推荐用utf8mb4_bin而不是默认的utf8mb4_general_ci原因是 Flowable 引擎判断一些业务标识如PROC_DEF_ID_、TASK_DEF_KEY_时会做精确匹配用bin排序规则更严格避免大小写问题导致的匹配意外。第二步进入数据库按顺序执行脚本。命令行方式如下mysql -uroot -p flowable flowable.mysql.create.common.sql mysql -uroot -p flowable flowable.mysql.create.identitylink.sql mysql -uroot -p flowable flowable.mysql.create.entitylink.sql mysql -uroot -p flowable flowable.mysql.create.eventsubscription.sql mysql -uroot -p flowable flowable.mysql.create.engine.sql mysql -uroot -p flowable flowable.mysql.create.job.sql mysql -uroot -p flowable flowable.mysql.create.history.sql如果你用的是 Navicat、DataGrip 这类图形化工具直接打开 sql 文件执行也行但要注意 DataGrip 需要先把当前连接的数据库切换到flowable不然表会建到默认数据库里。第三步验证表是否建成功。USE flowable; SHOW TABLES LIKE ACT_%;正常情况下列出的表数量在 60 张左右具体数量与 Flowable 版本和模块配置有关。如果看到ACT_GE_PROPERTY表再验证一下版本数据SELECT * FROM ACT_GE_PROPERTY WHERE NAME_ schema.version;返回值应该是6.7.2.0这样带版本号的值如果不一样说明脚本和引擎版本不匹配。第四步检查外键约束。MySQL 下即使按顺序执行也可能因为sql_mode设置有差异导致外键创建失败。执行SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE FOREIGN KEY AND CONSTRAINT_SCHEMA flowable;Flowable 引擎表之间外键数量有几十个如果这里是 0说明外键全没建上需要检查建表过程有没有跳过错误。3.2 Oracle 环境下的建表全过程含表空间与授权Oracle 这边建议用 sysdba 或具备 DBA 权限的账号来执行建表脚本因为脚本里可能包含建序列CREATE SEQUENCE的权限要求。普通业务账号如果没有 CREATE SEQUENCE 权限执行到一半就会报错。第一步确认数据库版本和字符集。SELECT * FROM v$version; SELECT value FROM nls_database_parameters WHERE parameter NLS_CHARACTERSET;如果是AL32UTF8那VARCHAR2和NVARCHAR2都没问题。如果是ZHS16GBK或其它字符集优先用NVARCHAR2字段Flowable 的 Oracle 脚本已经考虑了这一点。第二步创建表空间和业务账号。如果公司规范要求用现有表空间这一步可以跳过但你需要把脚本里所有TABLESPACE FLOWABLE替换成自己的表空间名。第三步执行脚本。命令行方式sqlplus flowable_user/passwordORCL flowable.oracle.create.common.sql sqlplus flowable_user/passwordORCL flowable.oracle.create.identitylink.sql顺序与 MySQL 一致。注意 sqlplus 执行时如果遇到ORA-01950: no privileges on tablespace这种错误说明账号没有对应表空间的配额需要授权ALTER USER flowable_user QUOTA UNLIMITED ON FLOWABLE;第四步验证表数量。Oracle 的验证语句SELECT COUNT(*) FROM user_tables WHERE table_name LIKE ACT\_% ESCAPE \;因为ACT_中的下划线在 Oracle 里是通配符需要转义。正常会有 60 张左右的 Flowable 业务表加上ACT_EVT_LOG之类的日志表。3.3 建表脚本执行成功的验证方法验证不只是看表存在还要确认表和索引的状态都正常。MySQL 下可以看表和索引信息SELECT table_name, table_rows, engine FROM information_schema.tables WHERE table_schema flowable; SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema flowable;Oracle 下检查表和索引SELECT table_name, status FROM user_tables WHERE table_name LIKE ACT\_% ESCAPE \; SELECT index_name, status FROM user_indexes WHERE table_name LIKE ACT\_% ESCAPE \;所有 status 都应该是VALID。如果有INVALID状态说明建表过程有异常需要排查。另外一个很实用的检查方式直接启动一个空的 Flowable Spring Boot 应用配置数据源指向建好的库看启动日志里有没有Flowable database schema update相关的操作。如果引擎检测到版本一致且表结构完整日志会显示类似Using default history level这样的信息不会有 DDL 执行的记录说明建表完全成功。4. 常见问题、报错汇总与排查技巧4.1 典型报错速查表我把实战中碰到的报错按场景整理成了表格方便你对照排查。报错信息数据库原因分析解决思路ORA-00959: tablespace FLOWABLE does not existOracle脚本里指定了 FLOWABLE 表空间但实例里没有创建对应表空间或全局替换脚本中的表空间名ORA-00922: missing or invalid optionOracle脚本在低版本 sqlplus 下执行或某些语法兼容性问题确认 Oracle 版本为 12c 及以上尽量用 sqlplus 18c 客户端执行ORA-01950: no privileges on tablespaceOracle账号没有表空间配额权限执行 ALTER USER 授予配额ORA-00904: invalid identifierOracle脚本中引用了不存在的列通常为脚本与数据库版本不匹配核对脚本版本是否 6.7.2不要混用其他版本的建表语句ERROR 1215 (HY000): Cannot add foreign key constraintMySQL表创建顺序不对或关联字段类型不一致严格按官方顺序执行检查两个关联表的字段类型是否一致尤其 varchar 长度、charsetERROR 1071 (42000): Specified key was too longMySQL索引字段太长超出 767 字节或 3072 字节限制确认 InnoDB 的 innodb_large_prefix 已开启8.0 默认开启或建库时使用 utf8mb4 并限定字段长度Table flowable.ACT_GE_PROPERTY doesnt existMySQLcommon 脚本没执行或执行失败先建 common 表并确认 ACT_GE_PROPERTY 里 schema.version 已写入启动时 Flowable 报 schema version mismatch通用引擎 JAR 版本与库里的 schema.version 不一致使用配套的 6.7.2 引擎版本或执行对应版本的 upgrade 脚本4.2 我亲历的几个坑和排查过程第一个坑MySQL 外键全部丢失。有次我在 MySQL 8.0 上执行完所有脚本后SHOW TABLES看着没问题Flowable 应用也能启动但跑流程时某些操作异常慢。排查了半天发现information_schema.TABLE_CONSTRAINTS里外键数为 0。原因是当时用了图形化工具逐条执行前一个脚本的某条 SQL 报错后工具没有终止继续往后面执行导致 engine 表建出来了但外键约束全部失败。那次之后我的习惯是执行过程中把错误输出重定向到文件执行完统一搜错。MySQL 命令行方式mysql -uroot -p flowable flowable.mysql.create.engine.sql 2 engine_error.log第二个坑Oracle 表空间名全局替换时漏了注释里的内容。有次图省事用 Notepad 全局替换FLOWABLE把注释里的一句话也替换了虽然不影响 SQL 执行但后续排查问题时看注释完全对不上号折腾了一阵子。后来我改用正则精确匹配TABLESPACE FLOWABLE整串只替换表空间定义不碰注释。第三个坑MySQL 的sql_modeSTRICT_TRANS_TABLES导致日期插入失败。严格模式下如果表里CREATE_TIME_是datetime(6)而引擎在极少数情况下写入的字符串格式不匹配会报Incorrect datetime value。这个概率很低但一旦遇到就很隐蔽。可以把 MySQL 的sql_mode调整为不包含NO_ZERO_DATE但这个要看 DBA 的规范不建议为了省事随意改。4.3 执行脚本前必须先确认的 4 件事动手执行之前建议把下面 4 件事确认到位能避开绝大多数问题数据库版本是否符合要求。MySQL 5.7、Oracle 12c低了可能出现语法兼容问题。账号权限是否足够。MySQL 需要 CREATE、ALTER、INDEX、REFERENCES 权限Oracle 需要 CREATE TABLE、CREATE SEQUENCE、CREATE TRIGGER 权限。表空间规划是否明确。Oracle 下确认表空间名和账号配额MySQL 下确认库的字符集和排序规则。脚本版本和引擎版本是否匹配。6.7.2 的库就用 6.7.2 的脚本不要用 7.x 的脚本去初始化 6.7.2 的引擎。把这几步做在前头比报错后再回头看效率高得多。5. 建表脚本的后续维护与常见扩展场景5.1 Flowable 自身的版本升级脚本拿到 6.7.2 的建表脚本只是开始项目上线后还会面临版本升级。Flowable 官方在发布新版本时除了全量建表脚本还会提供upgrade目录下的增量升级脚本比如从 6.7.0 升到 6.7.2只需执行对应的 upgrade 脚本。upgrade 脚本同样区分 MySQL 和 Oracle不能混用。升级逻辑上没有太多玄学先把库备份再在维护窗口执行 upgrade 脚本最后启动新版引擎让引擎校验 schema 版本。我维护过的项目里6.x 系列内部小版本升级基本都平滑没有遇到数据迁移的坑但跨大版本就不一定了升级前务必仔细看官方的版本迁移文档。5.2 多数据库支持与国产数据库的扩展思路Flowable 官方原生支持 MySQL、Oracle、PostgreSQL、SQL Server、DB2 等但项目实际落地时国内企业经常有迁移到国产数据库的需求比如达梦、人大金仓、openGauss 这一类的。遇到这种情况很多团队的思路是找对应数据库下的兼容模式。达梦数据库的 Oracle 兼容模式下可以尝试直接执行 Oracle 版建表脚本但不能保证 100% 成功因为达梦对 Oracle 语法兼容不是完全覆盖NVARCHAR2、TIMESTAMP(6)这些数据类型达梦基本能映射但CONNECT BY、SEQUENCE这些行为可能有差异。我处理过类似场景建议的路径是先用达梦的 Oracle 兼容模式创建数据库实例拿 Oracle 建表脚本做兼容性测试逐个排查报错遇到不兼容的语句手工调整为达梦的方言写法这套流程比较耗时做一次大约需要 2 到 3 天但流程本身是可控的。5.3 建表脚本在自动化交付流水线中的使用建表脚本另一个常见场景是集成到 CI/CD 流程中。我在多个项目里把建表 SQL 放到 Flyway 或 Liquibase 里管理初始脚本作为V1__init_flowable_tables.sql后续升级脚本按版本递增命名。这样做的好处是数据库结构版本可控、环境迁移可重复不用每次手工建表。要注意的是Flowable 官方脚本本身不是 Flyway 格式放到 Flyway 里时脚本开头的注释和个别语句可能需要整理。另外 Flowable 的一些表上会创建索引而 Flyway 在部分数据库上执行 DDL 时会对事务有特殊处理MySQL 的 DDL 是隐式提交Flyway 的默认事务配置需要调整。我的方案是在 Flyway 配置里关掉 Flowable 脚本的flyway.baselineOnMigrate冲突单独用spring.flyway.locations指向一个只放 Flowable 脚本的目录和业务表脚本分开管理。6. 一点实操心得关于“会建表”和“用好表”最后分享一个我自己的体会。建表脚本这个东西表面上是一堆 SQL 文件执行完就算完事但真正用好 Flowable建表只是第一步。你至少要花时间弄清楚ACT_RU_*是运行时表、ACT_HI_*是历史归档表、ACT_ID_*是身份管理表遇到流程跑得慢先看ACT_RU_TASK和ACT_RU_EXECUTION的数据量再考虑要不要做历史数据归档。我见过太多项目上线半年后业务表数据量几十万、流程流转越来越慢的情况基本都是因为没人维护ACT_HI_*表的数据生命周期。Flowable 项目从建表那天开始就应该有对应的数据清理和归档计划而不是等慢了再想方案。如果你也是刚开始接触 Flowable建议先拿这套脚本把数据库建好然后用 Spring Boot 快速集成跑通一个最简单的请假流程。数据库层面跑通了后面整个引擎的机制学起来都会顺手很多。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进