ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

PowerJob迁移达梦数据库:从驱动配置到表结构改造全记录

PowerJob迁移达梦数据库:从驱动配置到表结构改造全记录 如果你的生产环境里还在用PowerJob做分布式任务调度某天突然被告知调度中心的存储数据库要统一迁到达梦你大概率会先在搜索引擎里碰一遍“PowerJob 达梦配置”这个关键词。我上个项目就卡在这个环节网上答案七零八落官方文档里也只写了MongoDB和MySQL完全没提达梦。这篇文章就是我完整走完一遍之后的配置记录适合正在做数据库统一选型改造、准备把PowerJob从MongoDB或MySQL模式迁到达梦的团队参考也适合那些第一次接触达梦、想少走弯路的人。整个改造过程里真正麻烦的不是“把连接串改成达梦”这一个动作而是驱动、方言、建表脚本三个层面都要动手。下面我会按我实际操作的顺序从PowerJob的存储机制讲起再到达梦环境准备、Server配置改造、表结构迁移最后到真实调度验证和坑位复盘。过程里我会把每一次报错、每一个判断依据都写清楚方便你对照排查。1. 先说清楚PowerJob的存储模式下达梦到底卡在哪1.1 PowerJob不只是“一个Java应用”它分成Server、Worker、Console三块PowerJob的架构里Server是调度中心的大脑负责接收调度请求、分配任务、维护任务实例状态、保存工作流和运行日志Worker是挂在业务应用里的执行器真正执行任务逻辑Console是一个前端控制台通过HTTP接口操作Server。这三者里只有Server需要持久化数据库Worker不直接连数据库Console也不接触数据库。所以整个达梦适配的焦点很明确让PowerJob Server能正常读写达梦。这个架构对排查问题很有帮助。很多人一开始以为Worker那边也要改数据源其实不用。如果你发现调度链路不通先判断是Server连不上达梦还是Server和Worker之间的网络通信有问题两者完全不是一回事。1.2 PowerJob的SQL模式依赖JPA/Hibernate这不是随便配个数据源就能跑的PowerJob对存储的设计是双引擎默认可以用MongoDB也可以切到SQL模式。SQL模式底层用的是Spring Data JPA和Hibernate任务定义、任务实例、工作流节点、应用信息、用户信息这些都会落到关系型表里。也就是说只要能让Spring Boot项目里的DataSource指向达梦并且Hibernate能正常做映射和查询理论上就能让它跑在达梦上。但“理论上能跑”和“实际能跑”之间隔了三座山第一PowerJob官方Release包里没有达梦JDBC驱动你直接配置dm.jdbc.driver.DmDriver会报ClassNotFoundException第二PowerJob没有内置达梦的Hibernate方言数据库连接虽通但Hibernate在启动时可能无法确定方言后续生成的分页SQL、自增SQL也可能不对第三官方初始化SQL是MySQL血统字段类型、自增写法、表注释、表选项都带着很明显的MySQL痕迹达梦不认。这三点刚好对应了你后续要做的三件事引入达梦驱动、配置Hibernate方言、把MySQL风格的DDL改造成达梦能执行的版本。顺序上我建议先搭建达梦环境和准备驱动再改配置最后处理表结构这样每一步都有明确的验证点。2. 环境准备达梦建库、驱动定位、PowerJob版本固定2.1 固定PowerJob版本别让版本差异干扰排障达梦适配本来就不是官方标准路径版本不固定会加大排查难度。我这次用的是PowerJob 4.3.x系列下面所有配置也都基于这个版本写。如果你用的是3.x或者更新的5.x配置项名称可能略有差异但整体思路一致先跑通最简单的连接再逐步处理表和SQL问题。我强烈建议你从源码构建PowerJob Server而不是直接拿官方Starter Jar硬改。原因有两个一是达梦驱动不在官方依赖里源码构建可以让你在pom里手动加进去二是后面如果遇到某个SQL语法达梦不兼容你大概率要修改PowerJob源码或自定义方言类从源码构建最方便。git clone https://github.com/PowerJob/PowerJob.git cd PowerJob git checkout v4.3.82.2 达梦侧创建用户、确认端口、准备连接工具达梦数据库我用的是DM8默认端口是5236。如果你的达梦实例是别人装的先用Navicat或者达梦自带的DM管理工具连上去确认实例状态。新版Navicat可以直接选择“达梦”数据库类型填主机、端口、用户名、密码就能连上这一点比很多人的预期要友好。接下来创建一个专门给PowerJob用的用户。这里要注意达梦和MySQL的一个很大区别达梦里一个用户通常对应一个模式Schema你连接某个用户之后默认访问的就是这个用户的Schema。所以创建独立用户这件事不仅是权限管理更是Schema隔离。CREATE USER POWERJOB IDENTIFIED BY PJdm123 DEFAULT TABLESPACE USERS; GRANT DBA TO POWERJOB;测试环境我直接给了DBA权限省去一堆建表、建索引、建序列的权限扯皮。生产环境建议按最小权限给但至少要确认这个用户有建表、建索引、增删改查的权限。达梦里如果权限不足可能连建表时报错都看不明白所以这一步别省略。另外可以顺手确认一下这个达梦实例的兼容模式。达梦支持Oracle兼容、MySQL兼容等不同模式访问管理工具或者查V$DM_INI里COMPATIBLE_MODE参数就能看到。我的实例是Oracle兼容模式后面配置Hibernate方言时就可以用OracleDialect做底子。2.3 达梦JDBC驱动不在Maven中央仓库需要手动安装达梦JDBC驱动一般就在达梦安装目录下路径类似dmdbms/drivers/jdbc/DmJdbcDriver18.jar。DM8对应的Java 8及以上版本基本都是DmJdbcDriver18.jar。如果你手边没有达梦安装目录可以去达梦官网下载对应的JDBC驱动包。这个驱动不在公共Maven中央仓库所以要么放到你们公司的私服要么先通过install-file命令装到本地Maven仓库mvn install:install-file -DfileDmJdbcDriver18.jar \ -DgroupIdcom.dameng -DartifactIdDmJdbcDriver18 \ -Dversion8.1.1.49 -Dpackagingjar装好之后后续在PowerJob Server模块的pom里加依赖就能被正常解析了。如果跳过这步直接在源码里加坐标也会找不到包。3. 让PowerJob Server用上达梦数据源配置项与修改细节3.1 在源码构建阶段把达梦驱动引入Server模块PowerJob是个Maven多模块项目Server是独立的powerjob-server模块。你需要在这个模块的pom文件里手动增加达梦驱动依赖坐标就使用刚才install-file时指定的groupId、artifactId和version。加完之后在项目根目录执行mvn clean package -DskipTests打包完成后到powerjob-server的target目录下找到最终的可执行Jar确认里面包含了达梦驱动。如果不确认可以用jar tf查看一下有没有DmJdbcDriver18.jar这一步能避免后面启动时白折腾。这里有个细节值得单独说有人会觉得“我用官方现成的Jar包启动时通过-Dloader.path指向一个外部驱动目录不就行了”实际操作中不一定可行因为Spring Boot Fat Jar默认的启动器并不是PropertiesLauncherloader.path不一定生效。与其研究这个不如直接从源码构建一次把驱动问题彻底解决。3.2 修改数据源和JPA配置在PowerJob Server的配置文件里核心要改的是三块数据源连接信息、JPA方言、DDL生成策略。下面是我跑通的配置示例spring.datasource.driver-class-namedm.jdbc.driver.DmDriver spring.datasource.urljdbc:dm://127.0.0.1:5236?schemaPOWERJOB spring.datasource.usernamePOWERJOB spring.datasource.passwordPJdm123 spring.jpa.database-platformorg.hibernate.dialect.OracleDialect spring.jpa.hibernate.ddl-autonone spring.jpa.show-sqltrue spring.jpa.properties.hibernate.format_sqltrue逐项解释一下driver-class-name要写dm.jdbc.driver.DmDriver这是达梦JDBC的驱动类名不能写成MySQL驱动。URL格式是jdbc:dm://主机:端口后面用?schemaPOWERJOB指定模式。如果连接用户本身就是POWERJOB不指定也能路由到同名的Schema但如果你用的是一个有权限的管理员账号连接那就一定要指定schema否则后面会时不时报“表或视图不存在”。spring.jpa.database-platform指定为org.hibernate.dialect.OracleDialect。因为达梦默认兼容Oracle用OracleDialect生成的分页SQL、日期函数至少在语法层面是达梦能接受的。如果你们达梦实例是MySQL兼容模式也可以试试org.hibernate.dialect.MySQLDialect但我不建议一上来就赌这个先用OracleDialect更接近达梦的默认形态。spring.jpa.hibernate.ddl-autonone很关键。别让Hibernate自动建表因为Hibernate按实体生成的DDL很多是通用SQL到达梦上经常因为对象名大小写、字段类型、索引命名等问题中断。正确做法是先手动把表结构建好再让应用用none模式只做读写。show-sql建议开一段时间排查问题结束后再关掉。3.3 保留PowerJob自身通信配置避免把数据库问题和通信问题混在一起PowerJob Server除了HTTP接口之外还有Akka通信端口用来和Worker通信。数据库切换时这些通信相关的配置不要动。我见过有人把数据源配置改成达梦之后顺手把Akka端口也改了一个不冲突的结果启动是启动了Worker怎么都连不上Server排查了半天最后才发现是端口没对应上。所以这一阶段的策略是只动数据源和JPA相关配置其他配置保持官方默认。如果手工改过端口、IP之类的参数先回退等数据库链路完全跑通了再调整通信层。4. DDL迁移官方MySQL建表脚本改造成达梦的实操4.1 先拿到一套可信的PowerJob表结构PowerJob SQL模式下会用到一堆表核心的包括app_info应用信息也就是Worker注册的执行器应用job_info任务定义instance_info任务实例状态workflow_info工作流定义workflow_node_info工作流节点container_info容器信息server_infoServer节点信息user_info控制台用户从哪拿到表结构最靠谱我推荐一个很实用的做法先用PowerJob官方支持的MySQL模式在本地起一个MySQL实例让PowerJob Server以ddl-autoupdate跑起来JPA会自动把整套表结构建好。然后用Navicat导出这个MySQL库的表结构SQL。这份SQL就是你做达梦迁移的“母版”表名、字段名、字段类型都和你的PowerJob版本完全对应比在网上找任何旧脚本都稳。如果你不想在中间引入MySQL也可以直接从PowerJob源码里找实体类对照Table、Column注解去手写达梦DDL但那样效率低而且容易漏字段。用MySQL生成母版再改造是最省事的路径。4.2 MySQL和达梦DDL的关键差异直接看这张表拿到MySQL版DDL之后按下面这张表对照改造MySQL写法达梦DM8Oracle兼容模式写法说明BIGINT AUTO_INCREMENTBIGINT IDENTITY(1,1)自增主键达梦用IDENTITYINTINT可直接保留TINYINT(1)SMALLINT布尔或小枚举类型建议用SMALLINTDATETIMETIMESTAMP时间字段替换TEXTCLOB大字段替换LONGTEXTCLOB大字段替换VARCHAR(255)VARCHAR(255)注意达梦VARCHAR按字节算中文占得多必要时加长COMMENTxxxCOMMENT ON TABLE/COLUMN ...注释语法完全不同ENGINEInnoDB DEFAULT CHARSETutf8mb4删除达梦没有表引擎和字符集子句反引号去掉或改成双引号达梦不认MySQL反引号这里最容易被忽略的是注释语法。MySQL里你可以写COMMENT任务表达梦不认必须拆成COMMENT ON TABLE JOB_INFO IS 任务信息表; COMMENT ON COLUMN JOB_INFO.JOB_NAME IS 任务名称;如果你从工具导出的DDL里全是MySQL风格一定要把COMMENT批量替换掉。4.3 job_info表改造示例下面以job_info任务表为例给出一份达梦版本的核心字段建表SQL。实际使用时你还是应该以自己导出的MySQL表结构为准这里主要是展示类型和自增处理方式。CREATE TABLE JOB_INFO ( ID BIGINT IDENTITY(1,1) NOT NULL, APP_ID BIGINT NOT NULL, JOB_NAME VARCHAR(255) NOT NULL, JOB_DESCRIPTION VARCHAR(255), JOB_TYPE SMALLINT NOT NULL, TIME_EXPRESSION VARCHAR(255), TIME_EXPRESSION_TYPE SMALLINT NOT NULL, EXECUTE_TYPE SMALLINT NOT NULL, PROCESSOR_TYPE SMALLINT NOT NULL, PROCESSOR_INFO VARCHAR(255), STATUS SMALLINT NOT NULL, MAX_INSTANCE_NUM INT DEFAULT 1, CONCURRENCY INT DEFAULT 1, PARAMETERS CLOB, LIGHTWEIGHT SMALLINT DEFAULT 0, GMT_CREATE TIMESTAMP, GMT_MODIFIED TIMESTAMP, PRIMARY KEY (ID) ); COMMENT ON TABLE JOB_INFO IS 任务信息表; COMMENT ON COLUMN JOB_INFO.JOB_NAME IS 任务名称;字段顺序、类型请以你的PowerJob版本为准但这个写法能说明达梦DDL的几个核心差异自增用IDENTITY(1,1)布尔/枚举用SMALLINT大文本用CLOB注释用COMMENT ON。索引也要建否则任务量一大查询会卡CREATE INDEX IDX_JOB_INFO_APP_ID ON JOB_INFO(APP_ID);4.4 表名大小写和引号问题一杯水端平达梦默认把所有不带引号的标识符转成大写存储。也就是说你写CREATE TABLE job_info和写CREATE TABLE JOB_INFO最终在数据字典里几乎都是大写JOB_INFO。PowerJob的Hibernate实体映射在生成SQL时如果没有显式开启globally_quoted_identifiers生成的表名一般不带引号比如select ... from job_info。这种SQL到达梦后达梦会自动把job_info转成JOB_INFO去匹配表所以只要你建表脚本里的表名不是带双引号的小写一般都能对上。最忌讳的做法是有些表用带双引号的小写建有些表用不带引号的方式建。这样表存储的大小写状态不一致跑着跑着就会出现“表或视图不存在”。我的建议是统一用不带引号或统一用大写脚本别混。初始化数据这块PowerJob控制台首次打开会让你创建管理员账号并引导初始化命名空间所以用户相关的INSERT脚本通常不需要你手工准备。但如果你看到某个表一直查不到数据比如namespace没有默认记录需要检查是不是表写入权限不够或者初始化事务被某个DDL错误中断了。5. 启动阶段真实踩坑从连接失败到分页SQL报错5.1 启动就报ClassNotFoundException先怀疑驱动没进classpath我第一次把配置改成达梦后启动直接抛了类似这样的异常Caused by: java.lang.ClassNotFoundException: dm.jdbc.driver.DmDriver这个报错最直接就是驱动类不在classpath里。很多人会去反复检查driver-class-name拼写但真正原因其实是Jar包里根本没有达梦驱动。如果你是源码构建的先打开最终Jar包确认BOOT-INF/lib下有没有DmJdbcDriver18.jar。如果不在回过去检查pom依赖有没有真正被加载或者mvn install-file时version信息是否和pom里写的一致。还有一种情况是你用了别人构建好的镜像或Jar包里面没有达梦驱动那就只能自己重新构建或者在部署层想办法把驱动塞进classpath。5.2 数据库连接URL报错先分清是网络问题、驱动问题还是Schema问题连接失败有很多种形态。最常见的是Communications link failure或者Connection refused达梦端口5236不通。先检查服务是否真的在监听再检查防火墙。这个跟咱们配置本身关系不大但最容易浪费排查时间。驱动类能加载但连接串报错看一下URL格式是不是jdbc:dm://主机:端口。达梦不需要像MySQL那样写?useUnicodetruecharacterEncodingUTF-8这些但如果你需要指定schema可以用?schemaPOWERJOB。连接成功但查询说“表或视图不存在”十有八九是当前连接用户对应的Schema不对。你如果用了一个管理员账号连接它的默认Schema不是POWERJOB那它看不到POWERJOB下的表。解决办法就是在连接串里显式加上?schemaPOWERJOB或者连接时就用POWERJOB用户。5.3 Hibernate方言报错让达梦先用OracleDialect跑起来连接通了之后启动日志里可能出现org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfoException: Unable to determine Dialect原因就是Hibernate不认识达梦驱动返回的数据库产品名无法自动匹配方言。解决办法已经在配置里写了指定spring.jpa.database-platformorg.hibernate.dialect.OracleDialect。有些环境用了OracleDialect之后后面启动还是会遇到一些SQL函数或分页语法不兼容。这时候建议在PowerJob源码里加一个自定义方言类继承OracleDialect然后在配置里把spring.jpa.database-platform指向你自己的类import org.hibernate.dialect.OracleDialect; public class DmDialect extends OracleDialect { public DmDialect() { super(); } }这样做的意义在于以后发现哪个函数、哪种分页语法达梦不认只需要在这个子类里重写对应方法而不用大范围改PowerJob代码。达梦和Oracle语法有九成相似OracleDialect已经能覆盖绝大多数情况剩下的一成用这个口子去补。5.4 出现LIMIT分页报错找到原生SQL的出处逐个改成达梦写法启动成功不代表所有功能都能用。我去控制台翻任务列表时遇到过SQL执行报错提示在LIMIT附近有语法错误。为什么OracleDialect还会把SQL写成LIMIT因为PowerJob某些查询可能是用原生SQL注解写的里面直接写了MySQL风格的LIMIT ?这种SQL不会交给Hibernate方言去做分页改写。排查思路也不复杂把报错SQL打出来在PowerJob源码里搜索LIMIT关键字找到对应的Mapper或Repository方法把它改成达梦能接受的形态。简单分页可以改写成ROWNUM风格复杂的可以考虑用子查询。改完之后重新构建再跑一遍对应的页面或接口。这种问题通常不是一次能排完的所以要有点耐心。我建议在启动和前期调试阶段保持show-sqltrue把SQL日志留全等所有页面和调度链路都验证过一遍再关掉。5.5 中文乱码优先检查库字符集和连接编码如果你在控制台创建任务名称时写的是中文之后在达梦里查出来是乱码这不是PowerJob的问题。先确认达梦数据库实例字符集是不是UTF-8再确认客户端连接工具的编码。应用侧连接串如果发现乱码可以尝试在URL里加上编码相关参数同时检查应用服务器默认编码。达梦对UTF-8的兼容整体是好的多数乱码都出在库初始化时字符集选错或者客户端跟服务端编码不一致。6. 验证链路控制台建任务、Worker接入、跑一个原子任务6.1 Server启动成功之后先完成控制台的首次初始化数据源和表结构都准备好之后启动Serverjava -jar powerjob-server-starter-4.3.8.jar \ --spring.datasource.urljdbc:dm://127.0.0.1:5236?schemaPOWERJOB \ --spring.datasource.usernamePOWERJOB \ --spring.datasource.passwordPJdm123看到启动日志里没有异常并且数据源相关初始化完成就可以打开PowerJob控制台。首次访问会进入初始化引导创建管理员账号选择命名空间。这一步能顺利通过说明用户表、命名空间表等关键表的读写都正常了。然后去控制台的“应用管理”里新增一个应用。这个应用名就是后续Worker配置里的app-name比如dm-demo-app。新增成功之后控制台会生成对应的AppId这一步能验证app_info表的读写。6.2 Worker不需要达梦配置但要保证Server可达很多人在这一阶段被绕晕为什么我的Worker连不上Server因为Worker压根不连接达梦它只通过Akka和Server通信。你只需要在你的业务应用里引入Worker依赖dependency groupIdtech.powerjob/groupId artifactIdpowerjob-worker/artifactId version4.3.8/version /dependency配置方面只需要关心Server地址和AppNamepowerjob.worker.server-address127.0.0.1:7700 powerjob.worker.app-namedm-demo-app powerjob.worker.port27777如果你在Server端改过Akka端口这里要和Server保持一致。其他数据库相关的配置在Worker这里一律不需要这就是PowerJob分层设计的好处。6.3 跑一个原子任务才算真正验证完成配置都就绪后别急着把项目接进来先写一个最简单的处理器验证链路import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import tech.powerjob.worker.core.processor.ProcessResult; import tech.powerjob.worker.core.processor.TaskContext; import tech.powerjob.worker.core.processor.sdk.BasicProcessor; Slf4j Component public class DmTestProcessor implements BasicProcessor { Override public ProcessResult process(TaskContext context) { log.info(达梦适配验证任务运行成功, instanceId{}, context.getInstanceId()); return new ProcessResult(true, success); } }在控制台新建一个固定频率任务表达式写成/5 * * * * ?这种每5秒触发一次的Cron处理器选择DmTestProcessor然后开启任务。等几秒钟去看任务实例状态应该能看到实例从等待调度变成运行中再变成成功。这一步非常关键因为它同时验证了任务定义读取、调度器运行、任务实例状态写入三个环节。很多项目建表通了、控制台能登录了就以为适配完成结果一跑真实任务状态更新SQL出问题整个调度链路根本没法用。我习惯在任务跑通后再做一次重启验证把Server停掉再启动然后去控制台看刚才跑过的任务实例历史记录还在不在。如果记录都在说明达梦持久化确实生效了如果表清空了或者查不到说明你连接的不是同一个Schema或者表初始化数据有问题。最后再提醒一个容易被忽略的部署细节如果你的运行环境不允许从源码构建而是直接拿官方Fat Jar在服务器上跑那你在做达梦适配时一定要把驱动一并处理别只改一个配置URL。另外任务实例和运行日志表增长很快达梦表空间记得做好规划和定时清理否则一两个月后表空间吃紧你会很难说清楚到底是调度框架的问题还是数据库运维没跟上。适配达梦这件事跑通只是开始能稳定跑下去才是目标。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表