Oracle方言升级需针对性适配:Liquibase需显式声明VARCHAR2(255 CHAR)语义;Flyway 8.5.13前需禁用SEGMENT CREATION DEFERRED;diffChangeLog漏NOT NULL需手动校验约束状态;RAC下需调优锁超时与服务名一致性。
Oracle 12c+ 使用 Liquibase 的 varchar2 长度限制问题
liquibase 默认把 varchar2(255) 当成字节长度,但 oracle 12c+ 默认是字符语义(nls_length_semantics=char),结果建表时实际变成 255 字符 —— 看似正常,一插入中文就报 ora-01461: can bind a long value only for insert into a long column。
必须显式声明语义,否则迁移脚本在不同环境行为不一致:
- 在
changelog.xml中用<column type="VARCHAR2(255 CHAR)">,别写255不带单位 - YAML 格式写成
type: VARCHAR2(255 CHAR),Liquibase 4.20+ 才原生支持;旧版本得用type: "VARCHAR2(255 CHAR)"加引号防解析错误 - 如果用 Java API 构造
Column,调用setDataType("VARCHAR2(255 CHAR)"),别依赖DataTypeFactory自动推导
Flyway 8.x 连接 Oracle 23ai 时的 ORA-00922: missing or invalid option
Flyway 8.5.13 之前版本生成的 CREATE TABLE 语句默认带 SEGMENT CREATION DEFERRED,而 Oracle 23ai 在某些租户模式下禁用该语法,直接报错。
绕过方式不是升级 Flyway(虽然推荐),而是精准控制方言行为:
- 在
flyway.conf或 Spring Boot 的application.yml中加配置:flyway.oracle.sqlTranslation=STANDARD(别用ORACLE模式) - 若用
flyway.locations指向 SQL 脚本,所有CREATE TABLE语句末尾手动删掉SEGMENT CREATION DEFERRED - Java 代码中创建
FluentConfiguration时,调用.oracleSqlTranslation(OracleSqlTranslation.STANDARD)
Liquibase diffChangeLog 在 Oracle 上漏掉 NOT NULL 约束
liquibase diffChangeLog 对 Oracle 的 ALL_CONSTRAINTS 和 ALL_CONS_COLUMNS 查询有缓存偏差:它只比对状态为 ENABLED 的约束,但 Oracle 新建字段加 NOT NULL 时,约束可能处于 ENABLED NOVALIDATED 状态 —— Liquibase 就当它不存在。
立即学习“Java免费学习笔记(深入)”;
检查和修复步骤:
- 手动查库确认:
SELECT constraint_name, status, validated FROM all_constraints WHERE table_name = 'YOUR_TABLE' AND constraint_type = 'C' - 生成前先执行
ALTER TABLE your_table MODIFY (col_name CONSTRAINT col_nn NOT NULL ENABLE VALIDATE) - 或改用
liquibase diff输出 JSON,再人工补addNotNullConstraint变更块,别依赖自动生成的 changelog
Flyway + Oracle RAC 环境下 flyway_schema_history 表锁超时
RAC 节点间全局队列同步慢,Flyway 默认 30 秒获取 flyway_schema_history 表锁,高并发启动时容易卡住,日志里反复出现 java.sql.SQLTimeoutException: ORA-01013: user requested cancel of current operation。
这不是网络问题,是锁策略太激进:
- 在 JDBC URL 后追加
?oracle.net.CONNECT_TIMEOUT=60000&oracle.net.READ_TIMEOUT=60000(单位毫秒) - Spring Boot 中设
spring.flyway.lock-retry-count=3,配合spring.flyway.lock-retry-delay=5000 - 关键:确保所有节点连接的是同一个 service name(不是单个实例名),否则锁根本不在同一视图下生效
Oracle 方言的自动升级从来不是“配好就跑”,每个版本的约束语义、锁机制、元数据查询路径都在变。你看到的“成功执行”,可能只是某个节点上的临时状态。










