mtk 存储过程迁移汉字乱码问题处理--NLS_LANG 不一定要跟数据库的字符集相同
mtk
解决存储过程乱码问题
数据库及版本 | 字符集 | |
---|---|---|
源库 | ORACLE 19.19 | 字符集 |
目标库 | MogDB 5.0.5 | ZHS16GBK |
先看 MTK 的数据库迁移报告汇总页面

开始时间是 2024-04-01 09:43:50 结束时间: 2024-04-02 16:55:29 ,历经 1天7小时,数据2.7T左右。
存储过程总共 164 个,失败了 90个。
点击查看详情,可以看到它的报错是:
失败原因:
code: 3F001 msg: schema “xxxxx” does not exist Line: 14 Position: 465
可以看到 out xxxxx.refCursor
这个是个包的名称,这里 mtk
识别为schema
的名称,这不是关键因素,继续查看,发现大部分存储过程都是汉字是乱码。
但是单独通过工具导出的存储过程汉字是正常的。
也就是 mtk
在获取存储过程的时候编码有问题。
注意 mtk 的字符集的设置有两个,一个是数据库的 charset,一个是客户端的 clientCharset。
根据 https://docs.mogdb.io/zh/mtk/v2.0/mtk-config#clientcharset
clientCharset
类型: string
描述: 针对数据库编码转换场景使用,一般情况下不需要设置.
- 主动配置下会检查源和目标是否一致,不一致则同步源设置,一致不处理
- 默认根据源字符集进行设置,尽量减少转码次数。 如源Oracle是ZHS16GBK则以GBK读取,目标端以GBK插入,如果目标端是GBK则不需要转码,是UTF8则在数据库内核层转码不在驱动层转码
如 Oracle ZHS16GBK 编码迁移到 openGauss UTF8. 遇到
ORA-29275: partial multibyte character
.
还有一个是 :charset
charset
类型: string
描述: 数据库字符集.
默认不用配置,连接数据库查询.
可选值:
- gbk
- utf8
的描述,这俩参数很强大,可以不用设置,会自动判断,但是在实施的过程会发现,存储过程的汉字会乱码。常存储过程是通过 dba_source
来获取的,检查部署 mtk
的主机的 NLS_LANG
设置为空,通过sqllus
查询 dba_source
发现是乱码,手工设置为 gbk
,也是乱码,后来设置为 utf8
之后,查询出来的dba_source
正常。同时也设置了xshell终端的字符集等,查询 dba_source
也是乱码,只有设置 NLS_LANG
为 utf8,查询正常。
1 | export NLS_LANG=AMERICAN_AMERICA.AL32UTF8 |
为了确保 mtk
获取的存储过程不是乱码,建议在终端设置 NLS_LANG
参数(NLS_LANG 不一定要跟数据库的字符集相同,见后面的oracle 官方文章的 关于 NLS_LANG 的常见误解:将 NLS_LANG 设置为数据库的字符集有可能正确,但大多数情况下都是不正确的。请勿假设 NLS_LANG 必须与数据库字符集相同。事实往往并非如此。)之后,
如何检测呢,我这边测试就是通过sqlplus
查询 dba_source
如果汉字不乱码,然后执行mtk就正常。
源端 ORACLE 数据库的字符集是ZHS16GBK
,但是 NLS_LANG
设置为 AMERICAN_AMERICA.AL32UTF8
是可以解决。设置为其他字符集比如跟数据库相同的字符集 ZHS16GBK
也是无法解决的。
之前总认为 NLS_LANG 的设置要跟数据库的字符集相同,后来查询资料发现这是错误的。https://www.oracle.com/cn/database/technologies/faq-nls-lang.html
关于 NLS_LANG 的常见误解
- 将 NLS_LANG 设置为数据库的字符集有可能正确,但大多数情况下都是不正确的。请勿假设 NLS_LANG 必须与数据库字符集相同。事实往往并非如此。
- 使用 NLS_LANG 参数定义字符集不会更改客户端的字符集。这是为了让 Oracle 知道您在客户端上所使用的字符集,以便 Oracle 可以做出正确的转换。如果您使用不同的 NLS_LANG 设置,这并不能更改客户端的字符集!
- 如果未在客户端上设置 NLS_LANG,则它将使用服务器的 NLS_LANG。同样,这可能是不正确的!例如,如果 Oracle 安装程序未填充 NLS_LANG,并且该参数没有另行设置,则其默认值为 AMERICAN_AMERICA.US7ASCII。语言是 AMERICAN,区域是 AMERICA,字符集是 US7ASCII。
- 设置 NLS_LANG 的 LANGUAGE 和 TERRITORY 参数与在数据库中存储字符的能力无关。如果将 NLS_LANG 设置为 JAPANESE_JAPAN.WE8MSWIN1252,由于 WE8MSWIN1252 不支持日语字符,因此不能存储日语。但是,将 NLS_LANG 设置为 AMERICAN_AMERICA.JA16SJIS 则可以存储日语,只要所输入的数据确实是 JA16SJIS,而且数据库也使用可以存储日语的字符集(如 UTF8 或 JA16SJIS)。
经过 设置之后,重新单独跑了mtk
的存储过程,汇总页面有一些清爽了。接近 100%成功,其中1个识别和警告是源端数据库就是失效的存储过程。


以上的乱码应该不是 MTK 的问题,以上不设置的时候 sqlplus 也是乱码,设置了之后,sqlplus 不是乱码之后,mtk 的结果也不是乱码。关于 NLS_LANG
的知识,待日后补充。
附件:
*Table C-1 NLS_LANG Parameter Values*
Operating System Locale | NLS_LANG Value |
---|---|
Arabic (U.A.E.) | ARABIC_UNITED ARAB EMIRATES.AR8MSWIN1256 |
Bulgarian | BULGARIAN_BULGARIA.CL8MSWIN1251 |
Catalan | CATALAN_CATALONIA.WE8MSWIN1252 |
Chinese (PRC) | SIMPLIFIED CHINESE_CHINA.ZHS16GBK |
Chinese (Taiwan) | TRADITIONAL CHINESE_TAIWAN.ZHT16MSWIN950 |
Croatian | CROATIAN_CROATIA.EE8MSWIN1250 |
Czech | CZECH_CZECH REPUBLIC.EE8MSWIN1250 |
Danish | DANISH_DENMARK.WE8MSWIN1252 |
Dutch (Netherlands) | DUTCH_THE NETHERLANDS.WE8MSWIN1252 |
English (United Kingdom) | ENGLISH_UNITED KINGDOM.WE8MSWIN1252 |
English (United States) | AMERICAN_AMERICA.WE8MSWIN1252 |
Estonian | ESTONIAN_ESTONIA.BLT8MSWIN1257 |
Finnish | FINNISH_FINLAND.WE8MSWIN1252 |
French (Canada) | CANADIAN FRENCH_CANADA.WE8MSWIN1252 |
French (France) | FRENCH_FRANCE.WE8MSWIN1252 |
German (Germany) | GERMAN_GERMANY.WE8MSWIN1252 |
Greek | GREEK_GREECE.EL8MSWIN1253 |
Hebrew | HEBREW_ISRAEL.IW8MSWIN1255 |
Hungarian | HUNGARIAN_HUNGARY.EE8MSWIN1250 |
Icelandic | ICELANDIC_ICELAND.WE8MSWIN1252 |
Indonesian | INDONESIAN_INDONESIA.WE8MSWIN1252 |
Italian (Italy) | ITALIAN_ITALY.WE8MSWIN1252 |
Japanese | JAPANESE_JAPAN.JA16SJIS |
Korean | KOREAN_KOREA.KO16MSWIN949 |
Latvian | LATVIAN_LATVIA``.BLT8MSWIN1257 |
Lithuanian | LITHUANIAN_LITHUANIA.BLT8MSWIN1257 |
Norwegian | NORWEGIAN_NORWAY.WE8MSWIN1252 |
Polish | POLISH_POLAND.EE8MSWIN1250 |
Portuguese (Brazil) | BRAZILIAN PORTUGUESE_BRAZIL.WE8MSWIN1252 |
Portuguese (Portugal) | PORTUGUESE_PORTUGAL.WE8MSWIN1252 |
Romanian | ROMANIAN_ROMANIA.EE8MSWIN1250 |
Russian | RUSSIAN_CIS.CL8MSWIN1251 |
Slovak | SLOVAK_SLOVAKIA.EE8MSWIN1250 |
Spanish (Spain) | SPANISH_SPAIN.WE8MSWIN1252 |
Swedish | SWEDISH_SWEDEN.WE8MSWIN1252 |
Thai | THAI_THAILAND.TH8TISASCII |
Spanish (Mexico) | MEXICAN SPANISH_MEXICO.WE8MSWIN1252 |
Spanish (Venezuela) | LATIN AMERICAN SPANISH_VENEZUELA.WE8MSWIN1252 |
Turkish | TURKISH_TURKEY.TR8MSWIN1254 |
Ukrainian | UKRAINIAN_UKRAINE.CL8MSWIN1251 |
Vietnamese | VIETNAMESE_VIETNAM.VN8MSWIN1258 |
原文作者: Hi.MogDB
原文链接: https://hi.mogdb.org/posts/f4a90812/
许可协议: 知识共享署名-非商业性使用 4.0 国际许可协议