ORA-12712 错误表明新字符集非旧字符集超集,Oracle 仅允许 ZHS16GBK 升级至 AL32UTF8;降级不可行,强行操作必丢数据,且 CSSCAN 扫描与 ALTER DATABASE 变更需严格遵循三步闭环流程并确保三端字符集一致。
ORA-12712 新字符集必须是旧字符集的超集?
不是必须,但 oracle 强制要求新字符集在 al32utf8 到 zhs16gbk 方向转换时“向下兼容”——实际是反的:zhs16gbk 不是 al32utf8 的超集,所以从 al32utf8 改成 zhs16gbk 在 oracle 里根本不可行,会直接报 ora-12712。
真正能走通的只有单向:从 ZHS16GBK 升级到 AL32UTF8。降级(AL32UTF8 → ZHS16GBK)没有官方支持路径,强行导出再导入也大概率丢数据,尤其含 emoji、生僻字、多语言混合内容时。
- 检查当前字符集:
SELECT * FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET'; -
ZHS16GBK只能存 GBK 编码范围内的汉字(约 21886 字),超出即乱码或截断 -
AL32UTF8支持全部 Unicode 字符,但每个中文占 3 字节,空间略增
用 CSSCAN 扫描 ZHS16GBK 库能否安全升级到 AL32UTF8
CSSCAN 是 Oracle 提供的字符集扫描工具,但它只对源库为 ZHS16GBK 且目标设为 AL32UTF8 有意义;对反向操作它不输出有效建议,甚至可能跳过非法字符直接报 “no convertible data”,造成误判。
运行前必须停应用、关闭归档(或确保无活跃事务),否则扫描结果不准。
- 执行命令示例:
csscan username/password FULL=Y TOCHAR=AL32UTF8 LOG=scan_zh2utf CAPTURE=Y - 重点看生成的
scan_zh2utf.out中 “Convertible” 和 “Truncation” 行数 —— 若非零,说明有字段值在转换后长度超限(如VARCHAR2(10)存了 4 个中文,在ZHS16GBK占 8 字节,转AL32UTF8后占 12 字节,会截断) - 别信 “All character data is convertible” —— 它不校验列定义长度,只看字节映射是否合法
ALTER DATABASE CHARACTER SET AL32UTF8 报 ORA-12720 怎么办
这个错误意味着数据库不是在 MOUNT 状态下执行,或者当前用户没 ALTER DATABASE 权限,更常见的是:你试图跳过 CSSCAN 直接硬切,Oracle 拒绝这种高危操作。
正确流程必须是三步闭环:停库 → STARTUP MOUNT → ALTER SYSTEM ENABLE RESTRICTED SESSION → 执行变更。
- 必须用
SYS用户连接:sqlplus / as sysdba - 不能在
OPEN状态下执行,否则报ORA-12720 - 执行前确认无其它实例连着该控制文件(RAC 环境要全停)
- 变更后首次
OPEN会触发全库字符验证,若发现不一致数据(如已损坏的NCHAR列),可能卡住或报ORA-12713
改完 AL32UTF8 后应用连不上或中文变问号
不是数据库没改成功,而是客户端环境没同步。Oracle 字符集生效靠三端匹配:服务端(NLS_CHARACTERSET)、客户端 NLS_LANG、应用连接字符串里的字符集声明。
比如 Java JDBC 连接串漏了 ?useUnicode=true&characterEncoding=UTF-8,或者 Linux 终端的 LANG 还是 zh_CN.GB18030,都会导致显示异常。
- Linux 下临时生效:
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8 - Windows 注册表路径:
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_*下改NLS_LANG值为AMERICAN_AMERICA.AL32UTF8 - SQL*Plus 连入后立即查:
SELECT * FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_LANGUAGE';确认会话层也对齐
最常被忽略的是中间件(如 WebLogic、Tomcat)自身的 JVM 启动参数没加 -Dfile.encoding=UTF-8,导致 String 内部编码和数据库脱节——这时候查数据库是好的,打印日志却是乱码。










