Oracle到TiDB迁移 生僻字乱码问题解决方案

网友投稿 493 2024-02-23



背景

某去O场景业务上线测试,再执行某张表缩字段时报错。

***到TiDB迁移 生僻字乱码问题解决方案

现象

执行缩字段语句

ALTER TABLE schemaname.tablename MODIFY COLUMN licenseno varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT 发动机号 ;

报错信息

"incorrect string value \xED for column ‘licenseno’"

数据库版本

推测原因

TiDB报错"incorrect string value \xED for column ‘licenseno’",一般来说此类报错出现在插入语句阶段,用户在插入与字符集集不匹配的非法字符时报错。而题主本次进行进行的缩字段语句,其原理操作步骤大致分为:将相关表数据由 KV 全部 LOAD 到 TIDB 内存中,在内存中进行修改数据,将修改完的数据进行合规性校验,检验完成后回填到 KV 中。

所以推测是在数据回填进行合法性校验时出现了错误。

查看数据库字符集

character_set_client utf8mb4 character_set_connection utf8mb4 character_set_database utf8mb4 character_set_filesystem binary character_set_results character_set_server utf8mb4 character_set_system utf8 character_sets_dir /usr/local/mysql-5.6.25-osx10.8-x86_64/share/charsets/

查询原表中是否含有非法字符

select _tidb_rowid, convert(a using utf8mb4) from table where convert(a using utf8mb4) != a;

此时怀疑是不是 TiDB 对于一些生僻词不识别或者转储有错误。于是进行人工校验

结果插入正常,怀疑错误

此时回想数据来源,此数据是从 ORACLE 库中,通过 sqluldr2 导出成 CSV 文件,在通过 lighting 导入到 TiDB。合理怀疑链路过程某一环节有问题。单没有方向,只能从源头开始调查。

ORACLE端

查询数据正常,但对于生僻字来说肉眼看不一定准确,固将所见字转换为16进制。

ORACLE 16进制为 Typ=1 Len=10 CharacterSet=AL32UTF8: f0,a4,be,82,46,44,37,4d,36,38

TIDB 16进制为 EDA193EDBE824644374D3638

明显看到两边存储码不相同。

继续排查,sqluldr2 导出文件,建立一张测试表,仅插入所需数据,使用工具导出。然后通过VIM 命令 ":%!xxd" 查看字段16进制。明显看到此时转码已经出现问题,并不符合ORACLE存储的“f0,a4,be,82,46,44,37,4d,36,38”,而是转换成了“EDA193EDBE824644374D3638”。

另外存在疑问,导入时为何不进行数据合法性校验。咨询相关人员得到如下建议:使用lighting导入时,若原csv文件为utf8或binary编码,则lighting导入时不进行任何设置。导入模式为 kv 时的方法,不存在问题。若导入时csv文件为其他编码格式,且未使用 data-character-set 参数时,则 lighting 会默认 csv 文件是二进制编码且直接使用 utf8 格式,此时转码可能会存在未知问题。

结语

使用三方工具还是存在一些风险,不过目前此方案确实迁移速度较快(相比较于 KTL 工具)。另外听PingCap 正在推出自己的异构迁移工具,我司也正在进行内部测试,总体来说其速度相对于 kettle 还是比较快,但仍赶不上 sqluldr2 导出 lighting 的速度,且目前还存在一些问题,待我方测试完成后,各位如有兴趣,我会献上测评。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:mssql编写注册表解决方案(mssql 写注册表)
下一篇:使用MSSQL字符串比较大小,轻松解决问题(mssql字符串比较大小)
相关文章