背景
最近在反对一个从 Oracle 转 TiDB 的我的项目,为不便利用端兼容性测试须要把 Oracle 测试环境的库表构造和数据同步到 TiDB 中,因为数据量并不大,所以怎么不便怎么来,这里应用 CSV 导出导入的形式来实现。
整个过程能够分为三个步骤:
- 库表构造转换
- 源数据导出
- 导入指标库
库表构造转换
家喻户晓 TiDB 是兼容 MySQL 协定的,所以 Oracle 的表构造定义在 TIDB 不肯定能齐全应用,这时候就须要做一些转换,比方字段类型、关键字、零碎函数等等。如果表比拟少的话,手动转一下也不是不行,但本次测试的 Oracle 其中一个用户下就有将近 900 张表,手动去转换显然不可能。
这里我应用的工具是 TransferDB,它能够反对异构数据 Oracle 到 MySQL/TiDB 的构造转换,我的项目主页 https://github.com/wentaojin/…。
这个工具由 PingCAP 某位大佬开发,尽管没有正式对外公布,但的确挺好用的。TransferDB 是 TiDB 运维常用工具集(TiDBA)中的一部分,其余的还蕴含收集统计信息、Mok 解析 key、基于 region key、数据 range、数据估算生成打散语句、查看表数据以及索引 region leader 散布、版本升级,比对 3.0 以及 4.0 配置文件以及 tidb 零碎变量等,能够说是十分实用了,它的我的项目主页是 https://github.com/wentaojin/…
应用过 Lightning 的敌人对这个工具的应用肯定不会生疏,从配置文件到运行程序简直能够说是一模一样,我的项目自带的操作手册也写的十分具体。
它蕴含以下几点外围性能:schema 转换、表构造查看、迁徙老本评估、数据迁徙(全量或增量)、CSV 导出等,其中有些性能目前还是试验个性,我这里只用到了它的外围个性 schema 转换。
它的配置文件参数十分丰盛,正文很清晰应用起来非常简单,对于 schema 转换场景来说,只须要批改 和
[target]
局部的连贯信息就行,具体的配置清单能够看这里:https://github.com/wentaojin/transferdb/blob/main/conf/config.toml
配置文件批改好当前,执行上面两条命令就能够实现转换:
# 这个过程是在指标库中生成一个迁徙元信息库,用来存储转换规则、断点信息等等,相似于 DM 中的 dm_meta 库
./transferdb --config config.toml --mode prepare
# 这个过程是实现 schema 转换,输入 sql 文件
./transferdb --config config.toml --mode reverse
执行成当前会生成 2 个 SQL 文件,一个叫 reverse_${sourcedb}.sql
,它是在 TiDB 中能够执行的 sql,另一个是 compatibility_${sourcedb}.sql
,它是 TiDB 不兼容的 sql,比方 Foreign Key、Constraint 等等,这部分 SQL 须要人工去评估下应用别的计划来实现。
接着,把 reverse_${sourcedb}.sql
导入到 TiDB 即可,罕用的两种形式:
- mysql -h -u -P < reverse.sql
- source reverse.sql
源数据导出
Oracle 数据导出到 CSV 文件我应用 sqluldr2 来实现,这是一款在 Oracle 应用十分宽泛的数据导出工具,它的特点就是玲珑、轻便、速度快、跨平台、反对自定义 SQL。
网上的材料比拟多,这里就不具体介绍怎么去应用了,作者(前阿里数据库大佬)也写了一份超级具体的文档,大家搜寻 sqluldr2 超具体应用教程 -loracle 数据导出工具及办法
即可。
sqluldr2 尽管很弱小,但它却不反对批量导出这点很让人蛊惑,没方法只能另辟蹊径来实现了。
我先把须要导出的表清单放到一个 txt 文件中:
./sqluldr2linux64.bin user=user/pwd@192.168.1.1:1521/orcl query='select table_name from all_tables where owner='test';' file=/tmp/tidb/sqluldr_tables.sql
再写一个批处理脚本把所有表进行导出:
#!/bin/bash
cat /tmp/tidb/sqluldr_tables.sql | while read line
do
echo $line
/tmp/tidb/sqluldr2linux64.bin user=user/pwd@192.168.1.1:1521/orcl query={$line} charset=UTF8 field=0x7c0x260x7c record=0x3d0x37 null=null file=/tmp/tidb/data/orcltest.{$line}.csv
done
这里有几点须要留神:
- 字段分隔符和换行符倡议应用简单的字符,最好应用多种组合字符(举荐应用 ASCII 码),这样能尽可能的避免出现导出的数据 value count 和 column count 不统一的状况。
- 导出的文件字符集设置成 UTF8 格局,防止数据导入到 TiDB 后呈现中文乱码
- 因为前面要应用 Lightning 导入 CSV,文件命名格局要合乎 Lightning 的要求,即{dbname}.{tablename}.csv
到这里数据就准备就绪了。
导入到 TiDB
往 TiDB 中导入 CSV 文件有两种罕用的形式,第一种就是 Lightning,第二种是 Load Data,无论是从操作上还是性能上我都举荐优先思考 Lightning,起因如下:
- Load Data 只能导入单个文件,Lightning 能够批量导入
- Lightning 以性能著称,反对多种后端模式,Load Data 只能走计算层,还有内存放大景象
- 对于异常情况,Lightning 能够断点续传,Load Data 要清理数据从新导入
单从 900 个 csv 文件来看,Lightning 相对是第一抉择。
这里贴一下 Lightning 的几项外围配置:
[tikv-importer]
# 抉择应用的 local 后端
backend = "local"
# 设置排序的键值对的长期寄存地址,指标门路须要是一个空目录
sorted-kv-dir = "/tmp/tidb/lightning_dir"
[mydumper]
data-source-dir = "/tmp/tidb/data"
no-schema = true
filter = ['*.*']
[mydumper.csv]
# 字段分隔符,反对一个或多个字符,默认值为 ','。separator = '|&|'
# 援用定界符,设置为空示意字符串未加引号。delimiter = ''# 行尾定界字符,反对一个或多个字符。设置为空(默认值)示意"\n"(换行)和"\r\n"(回车 + 换行),均示意行尾。terminator = "=%"
# CSV 文件是否蕴含表头。# 如果 header = true,将跳过首行。header = false
# CSV 文件是否蕴含 NULL。# 如果 not-null = true,CSV 所有列都不能解析为 NULL。not-null = false
# 如果 not-null = false(即 CSV 能够蕴含 NULL),# 为以下值的字段将会被解析为 NULL。null = '\N'
# 是否对字段内“\“进行本义
backslash-escape = true
# 如果有行以分隔符结尾,删除尾部分隔符。trim-last-separator = false
注意事项:
– 举荐应用 local 模式,这样应答 blob 类型的数据处理更敌对
– 不须要导入表构造,所以设置 no-schema = true
– 分隔符和换行符这些要和 sqluldr2 设置的一样
最初运行 Lightning 即可:
./tidb-lightning --config tidb.toml --checkrequirements=false
这个过程中我还发现了一个 Lightning 的 bug,前面我会尝试本人修复一下。
其余局部
至于 Oracle 的其余局部例如存储过程和自定义函数,也不必多想怎么去迁徙了,老老实实改代码去利用端实现。
视图的话我是先用 PLSQL 把视图导成 sql 文件再导入 TiDB 中,然而报错的比拟多,根本都是零碎函数和语法不兼容问题,这部分就波及 SQL 改写了,没有什么好的方法。
总结
在之前的我的项目中也应用过 DSG 来实现 Oracle 到 TiDB 的数据迁徙,但它毕竟是个纯商业性工具,先充钱能力玩,对于这种测试阶段来说不是太好的抉择。
当然了,官网公布的《TiDB in Action》一书中也给出了 Oracle 到 TiDB 的迁徙案例:https://book.tidb.io/session4…,它基于 Oracle 自家的 OGG 组件来实现,部署应用上略微有点麻烦。
本文提到的几个工具都是随取随用,不须要装置各种依赖环境,这对于我当初面对的这种没有网络没有 yum 源的服务器来说几乎太难受了,在这样的小数据量测试场景中不失是一种抉择。
更多好计划也欢送大家举荐,为 TiDB 生态助力。