合 Oracle迁移到MySQL工具之愚公(yugong)
背景
2008年,阿里巴巴开始尝试使用 MySQL 支撑其业务,开发了围绕 MySQL 相关的中间件和工具,Cobar/TDDL(目前为阿里云DRDS产品),解决了单机 Oracle 无法满足的扩展性问题,当时也掀起一股去IOE项目的浪潮,愚公这项目因此而诞生,其要解决的目标就是帮助用户完成从 Oracle 数据迁移到 MySQL 上,完成去 IOE 的重要一步工作。
项目介绍
名称: yugong
译意: 愚公移山
语言: 纯java开发
定位: 数据库迁移 (目前主要支持oracle / mysql / DRDS)
整个数据迁移过程,分为两部分:
- 全量迁移
- 增量迁移
过程描述:
- 增量数据收集 (创建oracle表的增量物化视图)
- 进行全量复制
- 进行增量复制 (可并行进行数据校验)
- 原库停写,切到新库
架构
说明:
- 一个Jvm Container对应多个instance,每个instance对应于一张表的迁移任务
- instance分为三部分
a. extractor (从源数据库上提取数据,可分为全量/增量实现)
b. translator (将源库上的数据按照目标库的需求进行自定义转化)
c. applier (将数据更新到目标库,可分为全量/增量/对比的实现)
方案设计
DevDesign:https://github.com/alibaba/yugong/wiki/DevDesign
全量方案
业界常用的全量方案有:
- 数据文件导入/导出,比如EXPDP/IMPDP, mysqldump/source, xtrabackup等
- ETL数据导入/导出,主要原理为使用JDBC数据查询接口
yugong在项目设计之初考虑去IOE数据迁移的灵活性和自定义能力,最终选择的方案为基于JDBC接口遍历数据.
相比于数据文件导入/导出,其优点:
- 灵活数据同步
- 支持异构数据
- 实现相对简单
缺点:
- 全量拉取需要配合增量使用,会有部分数据重复同步
- 性能和影响,一次性全量拉取,如果持续时间过长,如果此时数据库变更过多,会导致segment过大
增量方案
业界常用的增量方案有:
- 基于时间戳定时dump
- oracle日志文件,比如LogMiner,OGG
- oracle CDC(Change Data Capture)
- oracle trigger机制,比如DataBus , SymmetricDS
- oracle 物化视图(materialized view)
- ...
yugong在项目设计之初考虑去IOE数据迁移的灵活性,支持多种oracle版本,同时为降低DBA的运维成本,最终选择oracle物化视图作为我们的增量方案.
相比于其他,物化视图方案其优点:
- 原理简单,方便理解和学习,用户可以理解为一种固化的简易trigger模式
- 运维简单,DBA一次账户授权后,程序可按需create一张物化视图表即可完成增量订阅
- 相对透明,不需要像时间戳sql扫描依赖数据库表设计,也不需要关注oracle版本和服务器存储等
缺点:
- 性能和影响,类似于trigger机制会对源库的数据写入造成一定的性能影响.
快速开始
QuickStart:https://github.com/alibaba/yugong/wiki/QuickStart
a. oracle全量基于JDBC拉取数据,增量基于物化视图来实现,所以这里需要给oracle数据库账号开启特殊权限
1 2 3 | GRANT SELECT,INSERT,UPDATE,DELETE ON XXX TO XXX; #常见CRUD权限 GRANT CREATE ANY MATERIALIZED VIEW TO XXX; GRANT DROP ANY MATERIALIZED VIEW TO XXX; |
1. 下载yugong
直接下载,可访问:https://github.com/alibaba/yugong/releases,会列出所有历史的发布版本包的下载,比如以1.0.0版本为例子:
1 | wget https://github.com/alibaba/yugong/releases/download/yugong-1.0.0/yugong-1.0.0.tar.gz |
or
自己编译
1 2 3 | git clone git@github.com:alibaba/yugong.git cd yugong; mvn clean install -Dmaven.test.skip -Denv=release |
编译完成后,会在根目录下产生target/yugong-$version.tar.gz
2. 解压缩
1 2 | mkdir /tmp/yugong tar zxvf yugong-$version.tar.gz -C /tmp/yugong |
3. 配置修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | vi conf/yugong.properties # 源数据库,需要修改成自己的数据库信息 yugong.database.source.username=test yugong.database.source.password=test yugong.database.source.type=ORACLE yugong.database.source.url=jdbc:oracle:thin:@127.0.0.1:1521:test yugong.database.source.encode=UTF-8 yugong.database.source.poolSize=30 # 目标数据库,需要修改成自己的数据库信息 yugong.database.target.url=jdbc:mysql://127.0.0.1:3306/test yugong.database.target.username=test yugong.database.target.password=test yugong.database.target.type=DRDS yugong.database.target.encode=UTF-8 yugong.database.target.poolSize=30 yugong.table.batchApply=true yugong.table.onceCrawNum=1000 yugong.table.tpsLimit=0 #use connection default schema yugong.table.ignoreSchema=false #skip Applier Load Db failed data yugong.table.skipApplierException=false #需要迁移的数据库表 yugong.table.white=yugong_example_oracle yugong.table.black= #tables use multi-thread enable or disable yugong.table.concurrent.enable=true #tables use multi-thread size yugong.table.concurrent.size=5 #retry times yugong.table.retry.times = 3 #retry interval or sleep time (ms) yugong.table.retry.interval = 1000 #MARK/FULL/INC/ALL(REC+FULL+INC)/CHECK/CLEAR yugong.table.mode=ALL #yugong extractor yugong.extractor.dump=false yugong.extractor.concurrent.enable=true yugong.extractor.concurrent.size=20 yugong.extractor.noupdate.sleep=1000 yugong.extractor.noupdate.thresold=0 yugong.extractor.once=false #{0} is all columns , {1}.{2} is schemaName.tableName , {3} is primaryKey #yugong.extractor.sql=select /+parallel(t)/ {0} from {1}.{2} t #yugong.extractor.sql=select * from (select {0} from {1}.{2} t where {3} > ? order by {3} asc) where rownum <= ? #yugong applier yugong.applier.concurrent.enable=true yugong.applier.concurrent.size=20 yugong.applier.dump=false #stats yugong.stat.print.interval=5 yugong.progress.print.interval=1 #alarm email yugong.alarm.email.host = smtp.163.com yugong.alarm.email.username = test@163.com yugong.alarm.email.password = yugong.alarm.email.stmp.port = 465 |
说明:
- 需要修改源和目标数据库的账号信息
- 需要修改yugong.table.white信息,登记需要同步的测试表
4. 准备测试表
a. 在源库oracle上创建一张待同步表
1 2 3 4 5 6 7 8 9 10 11 12 13 | create table yugong_example_oracle ( id NUMBER(11) , name varchar2(32) , alias_name char(32) default ' ' not null, amount number(11,2), score number(20), text_b blob, text_c clob, gmt_create date not null, gmt_modified date not null, CONSTRAINT yugong_example_oracle_pk_id PRIMARY KEY (id) ); |
b. 在目标库MySQL上创建一张目标表
Oracle到MySQL迁移:用华为云的DRS、阿里云的DTS、工具Navicat、kettle、OGG、dataX都可以,可以在本博客搜索
停止更新的工具,都不建议使用了,若有Oracle到MySQL的项目,目前个人使用感受比较好的工具包括华为云的DRS和Navicat工具。