写点什么

记一次简单的 Oracle 离线数据迁移至 TiDB 过程

  • 2022 年 7 月 11 日
  • 本文字数:3015 字

    阅读完需:约 10 分钟

原文来源:https://tidb.net/blog/9ae4a4c6


【是否原创】是


【首发渠道】TiDB 社区

背景

最近在支持一个从 Oracle 转 TiDB 的项目,为方便应用端兼容性测试需要把 Oracle 测试环境的库表结构和数据同步到 TiDB 中,由于数据量并不大,所以怎么方便怎么来,这里使用 CSV 导出导入的方式来实现。


整个过程可以分为三个步骤:


  • 库表结构转换

  • 源数据导出

  • 导入目标库

库表结构转换

众所周知 TiDB 是兼容 MySQL 协议的,所以 Oracle 的表结构定义在 TIDB 不一定能完全使用,这时候就需要做一些转换,比如字段类型、关键字、系统函数等等。如果表比较少的话,手动转一下也不是不行,但本次测试的 Oracle 其中一个用户下就有将近 900 张表,手动去转换显然不可能。


这里我使用的工具是 TransferDB,它可以支持异构数据 Oracle 到 MySQL/TiDB 的结构转换,项目主页[https://github.com/wentaojin/transferdb]()。


这个工具由 PingCAP 某位大佬开发,虽然没有正式对外发布,但确实挺好用的。TransferDB 是 TiDB 运维常用工具集(TiDBA)中的一部分,其他的还包含收集统计信息、Mok 解析 key、基于 region key、数据 range、数据估算生成打散语句、查看表数据以及索引 region leader 分布、版本升级,比对 3.0 以及 4.0 配置文件以及 tidb 系统变量等,可以说是非常实用了,它的项目主页是[https://github.com/wentaojin/tidba]()


使用过 Lightning 的朋友对这个工具的使用一定不会陌生,从配置文件到运行程序几乎可以说是如出一辙,项目自带的操作手册也写的非常详细。


它包含以下几点核心功能:schema 转换、表结构检查、迁移成本评估、数据迁移(全量或增量)、CSV 导出等,其中有些功能目前还是实验特性,我这里只用到了它的核心特性 schema 转换。


它的配置文件参数非常丰富,注释很清晰使用起来非常简单,对于 schema 转换场景来说,只需要修改[source][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 linedo 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}.csvdone
复制代码


这里有几点需要注意:


  • 字段分隔符和换行符建议使用复杂的字符,最好使用多种组合字符(推荐使用 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 = truefilter = ['*.*']
[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/chapter5/from-oracle-to-tidb.html](),它基于 Oracle 自家的 OGG 组件来实现,部署使用上稍微有点麻烦。


本文提到的几个工具都是随取随用,不需要安装各种依赖环境,这对于我现在面对的这种没有网络没有 yum 源的服务器来说简直太舒服了,在这样的小数据量测试场景中不失是一种选择。


更多好方案也欢迎大家推荐,为 TiDB 生态助力。


发布于: 刚刚阅读数: 2
用户头像

TiDB 社区官网:https://tidb.net/ 2021.12.15 加入

TiDB 社区干货传送门是由 TiDB 社区中布道师组委会自发组织的 TiDB 社区优质内容对外宣布的栏目,旨在加深 TiDBer 之间的交流和学习。一起构建有爱、互助、共创共建的 TiDB 社区 https://tidb.net/

评论

发布
暂无评论
记一次简单的Oracle离线数据迁移至TiDB过程_TiDB 社区干货传送门_InfoQ写作社区