Mysql数据迁移到udb

本节讲述 data2udb 工具的使用,此工具可以将 mysql表结构/数据/视图/函数/存储过程/触发器等 导出到文件,并对语法自动转换,最后将文件导入到udb。
结合ogg实现增量数据同步。

注意事项

  • 目标端对应数据库的表将被清除,如有重要数据请先备份

  • 需要 docker 环境

  • arm架构服务器仅支持全量迁移

  • 内存需大于4G

  • 数据导出时需要落到磁盘上,确保磁盘空间充足

  • 账号,密码,库名不建议有特殊字符

  • Mysql 版本需大于5.1.5

  • binlog_format 必须是 ROW

  • 必须存在和用户名相同的库名,仅用于连通性检查

  • 确保系统时间和源端目标端一致

  • Mysql认证插件只支持 mysql_native_password ,同时分配数据库只读权限. 例如: CREATE USER youruser@% IDENTIFIED WITH mysql_native_password BY 'yourpwd';  GRANT Index, Lock Tables, Select, Show Databases, Show View ON *.* TO youruser@%;.如果直接修改原有用户的认证插件,可能需要重新设置密码才生效.

  • 增量同步目前不支持停机迁移,需要先停止数据库写入,等全量导入完成后再允许写入.

  • 可以利用mysql从实例,源端使用从实例,结合 stop slave;start salve; 实现间接零停机增量同步到

  • 增量同步期间不支持表结构变更

操作步骤

准备连接信息—–下载容器镜像—–启动容器—–停止源端写入—–准备增量同步—–全量导出—–全量导入—–开启增量同步
以下以mysql5.7.41为例.

准备

检查源端和账号名相同的库名是否存在
检查源端是否开启bin_log show variables like "%log_bin%";, log_bin 值为ON,仅用于增量同步
检查源端binlog格式 show variables like "%binlog_format%";,binlog_format值为ROW,仅用于增量同步
准备源端和目标端账号/密码/端口/库名/信息
例如:
s_h=192.168.4.11 #源端地址
s_p=3309 #源端端口
s_s=tpcc #源端数据库名
s_d=tpcc #源端数据库名
s_u=root #源端账号
s_w=root #源端密码

d_h=192.168.4.11 #目标端地址
d_p=5678 #目标端口
d_d=tpcc_mysql #目标端库名
d_u=unvdb #目标端账号
d_w=tx #目标端密码

下载容器镜像文件

x86_64 http://download.unvdb.com/您的服务编码/source/tool/ogg/app/x86_64/data2udb.tar.gz
arm64 http://download.unvdb.com/您的服务编码/source/tool/ogg/app/aarch64/data2udb.tar.gz
服务编码联系技术支持获取

启动容器

导入docker镜像

docker load -i 容器镜像文件    
Loaded image: data2udb_x86:v24.8
#导入的镜像是 data2udb_x86:v24.8,下文使用此名称创建容器 

创建容器

docker run --network=host -it --name data2udb -e TZ=Asia/Shanghai -e s_h=源端地址 -e s_p=源端端口 -e s_s=源端数据库名 -e s_d=源端数据库名 -e s_u=源端账号 -e s_w=源端密码 -e d_h=目标端地址 -e d_p=目标端口 -e d_d=目标端数据库名 -e d_u=目标端账号 -e d_w=目标端密码 -e ty=full  data2udb_x86:v24.8 /bin/bash
#请对应修改账号信息和镜像名称  

停止源端写入,仅当增量同步时操作

如需使用增量同步,请务必停止源端写入操作.
或在从实例中执行 stop slave; 断开同步.

准备增量同步,仅当增量同步时操作

开启目标端接收

cat << EOF > /etc/odbc.ini
[unvdb]
Description = unvdb
Driver = /app/udb/lib/GGpsql25.so
Database = $d_d
Servername = $d_h
UserName = $d_u
Password = $d_w
PortNumber = $d_p
ReadOnly = 0
ConnSettings = set client_encoding to UTF8
EOF

cat << EOF > /app/udb/dirprm/repz.prm
replicat repz
SETENV(ODBCINI=/etc/odbc.ini)
SETENV(NLS_LANG=AMERICAN_AMERICA.ZHS16GBK)
TARGETDB unvdb,userid $d_u,password $d_w
DISCARDFILE ./dirrpt/repz.rpt, append
reportcount every 60 seconds, rate
cachemgr  cachesize  1G 
container  mem_limit  2G
map $s_d.*, target public.*;
EOF

启动目标端接收

cat << EOF > /tmp/2
start mgr
dblogin sourcedb unvdb
add checkpointtable public.checkpointtab
add replicat repz,exttrail ./dirdat/ea,checkpointtable public.checkpointtab
exit
EOF

/app/udb/ggsci paramfile /tmp/2 

开启源端提取

cat << EOF > /app/mysql/dirprm/extz.prm
extract extz
setenv (TZ="GMT+8")
-- 需要和database time zone as timestamp in MySQL 设置一致
sourcedb $s_u@$s_h:$s_p,userid $s_u,password $s_w
-- 必须存在和用户名相同的数据库
TRANLOGOPTIONS ALTLOGDEST REMOTE
-- 远程获取binlog数据 
-- tranlogoptions altlogdest /var/lib/mysql/mysql-bin.index 
-- 使用本地的binlog数据
rmthost 127.0.0.1, mgrport 8030, tcpbufsize 288750, tcpflushbytes 288750
RMTTRAIL ./dirdat/ea
discardfile ./dirrpt/extz.dsc, append
gettruncates
-- 默认情况下OGG 是不捕获truncate 操作,使用此参数捕获truncate。EXTRACT端和REPLICAT端都需要开启(有时目标端不开启也行)
cachemgr  cachesize  1G
container  mem_limit  2G
reportcount every 60 seconds, rate
table $s_d.*;
EOF

启动源端提取

cat << EOF > /tmp/2
start mgr
add ext extz, tranlog, begin now
add exttrail ./dirdat/ea, extract extz 
START EXTRACT extz
exit
EOF

/app/mysql/ggsci paramfile /tmp/2 

检查增量数据

确认 /app/udb/dirdat/ 目录下存在ea开头的文件

ls /app/udb/dirdat/ -al
total 4
drwxr-x--- 1 root root   33 Aug  5 10:50 .
drwxr-xr-x 1 root root  140 Aug  5 10:45 ..
-rw-r----- 1 root root 1336 Aug  5 10:50 ea000000000

执行全量导出

准备ddl导出配置文件

mkdir /data/oradata -p
cat <<EOF > /tmp/ddl.conf 
ORACLE_HOME        /usr/lib/oracle/19.10/client64/
ORACLE_DSN         dbi:mysql:host=$s_h;database=$s_s;port=$s_p
#支持以上3种方式
ORACLE_USER        $s_u
ORACLE_PWD         $s_w
SCHEMA             $s_s
USE_RESERVED_WORDS 1
#启用后关键字用双引号包起来
#INDEXES_SUFFIX _idx
#给索引名添加后缀,当索引跟表同名时,建议配置该项
INDEXES_RENAMING 1
#按照“表名_列名“的格式给索引重命名,当多次使用相同索引名或相同表名的数据库,建议开启
NULL_EQUAL_EMPTY 1
#把Null设置为空字符串
#oracle账号密码
#EXPORT_SCHEMA 1
#导出模式,默认为0
#CREATE_SCHEMA 1
#在导出的文件中创建模式,默认为0。这里的模式对应oracle用户名或者SCHEMA
TYPE               TYPE,TABLE,FUNCTION,GRANT,MVIEW,PARTITION,PROCEDURE,VIEW,TRIGGER,SEQUENCE,SYNONYM,SEQUENCE_VALUES
#导出表
PG_NUMERIC_TYPE    0
PG_INTEGER_TYPE    1
#DATA_TYPE          NUMBER:bigint
DEFAULT_NUMERIC    numeric
#SKIP               fkeys checks
#SKIP              keys pkeys ukeys indexes checks
#NLS_LANG           AMERICAN_AMERICA.UTF8
#设置字符编码
OUTPUT_DIR         /data/oradata
#输出sql目录
OUTPUT             ddl.sql
PG_VERSION         14
#STOP_ON_ERROR 0
PACKAGE_AS_SCHEMA 1
PREFIX_PARTITION 1
PREFIX_SUB_PARTITION 1
DISABLE_PARTITION 1
RENAME_PARTITION 1
TRANSACTION readonly
#JOBS                 6
#多个jobs会导致trigger分成多个文件
EOF

准备数据导出配置文件

cat << EOF > /tmp/data.conf
ORACLE_HOME        /usr/lib/oracle/19.10/client64/
ORACLE_DSN         dbi:mysql:host=$s_h;database=$s_s;port=$s_p
ORACLE_USER        $s_u
ORACLE_PWD         $s_w
SCHEMA             $s_s
TYPE               COPY
USE_RESERVED_WORDS 1
#启用后关键字用双引号包起来
#INDEXES_SUFFIX _idx
#给索引名添加后缀,当索引跟表同名时,建议配置该项
INDEXES_RENAMING 1
#按照“表名_列名“的格式给索引重命名,当多次使用相同索引名或相同表名的数据库,建议开启
NULL_EQUAL_EMPTY 1
#把Null设置为空字符串
#STOP_ON_ERROR 0
PG_NUMERIC_TYPE    0
PG_INTEGER_TYPE    1
DEFAULT_NUMERIC    numeric
#SKIP               fkeys checks
#SKIP              fkeys pkeys ukeys indexes checks
#NLS_LANG           AMERICAN_AMERICA.UTF8
OUTPUT_DIR         /data/oradata
OUTPUT             data.sql
FILE_PER_TABLE    1
#每个表导出为一个文件,默认所有数据导出到一个文件,当出现问题时不好解决。
PREFIX_PARTITION 1
PREFIX_SUB_PARTITION 1
DISABLE_PARTITION 1
RENAME_PARTITION 1
TRANSACTION readonly
JOBS                 32

#EXCLUDE           table1 example_.*
#排除表
#ALLOW   CUSTOMER,STUDENT,APPLICATION,EMPLOYEE
#只导出指定表
#PG_DSN             dbi:Pg:dbname=oracle;host=192.168.2.81;port=5678
#PG_USER            unvdb
#PG_PWD             udb
#PG_SCHEMA          soe
#以上几项开启时将直接导入udb,注意要先手动在udb创建好表和schema
PG_VERSION         14
EOF

开始导出

data2udb -c /tmp/ddl.conf
[========================>] 11/11 tables (100.0%) end of scanning.              
[========================>] 0/0 types (100.0%) end of output.     
[========================>] 11/11 tables (100.0%) end of table export.     
[========================>] 0/0 functions (100.0%) end of functions export.
[========================>] 0/0 materialized views (100.0%) end of output. 
[========================>] 0/0 partitions (100.0%) end of output.        
[========================>] 0/0 procedures (100.0%) end of procedures export.
[========================>] 0/0 views (100.0%) end of output.                
[========================>] 0/0 triggers (100.0%) end of output.
[========================>] 0/0 sequences (100.0%) end of output.
[========================>] 0/0 synonyms (100.0%) end of output. 
data2udb -c /tmp/data.conf
[========================>] 11/11 tables (100.0%) end of scanning.              
[========================>] 4/4 rows (100.0%) Table bmsql_config (0 sec., 4 recs/sec)
[========================>] 30000/28865 rows (103.9%) Table bmsql_customer (3 sec., 10000 recs/sec)                     
[========================>] 10/10 rows (100.0%) Table bmsql_district (0 sec., 10 recs/sec)                              
[========================>] 30218/30070 rows (100.5%) Table bmsql_history (1 sec., 30218 recs/sec)                      
[========================>] 100000/99444 rows (100.6%) Table bmsql_item (2 sec., 50000 recs/sec)                        
[=======================> ] 8992/9000 rows (99.9%) Table bmsql_new_order (0 sec., 8992 recs/sec)                     
[========================>] 30202/30195 rows (100.0%) Table bmsql_oorder (1 sec., 30202 recs/sec)                         
[========================>] 300831/297408 rows (101.2%) Table bmsql_order_line (13 sec., 23140 recs/sec)                    
[========================>] 100000/97506 rows (102.6%) Table bmsql_stock (7 sec., 14285 recs/sec)                           
[========================>] 1/1 rows (100.0%) Table bmsql_warehouse (0 sec., 1 recs/sec)                                
[========================>] 1/1 rows (100.0%) Table t1 (0 sec., 1 recs/sec)                                       
[========================>] 600259/592504 rows (101.3%) on total estimated data (27 sec., avg: 22231 tuples/sec)

执行全量导入

导入之前通过以下命令调整导入顺序,如主键外键触发器等需要在导入数据后执行.

提取主键外键

grep 'FOREIGN KEY' /data/oradata/TABLE_ddl.sql > /tmp/foreign.sql #提取外键  
grep '^ALTER TABLE' /data/oradata/TABLE_ddl.sql | grep -v 'FOREIGN KEY' > /tmp/alter.sql #提取主键
cp /data/oradata/TABLE_ddl.sql /tmp/TABLE_ddl.sql && sed -i '/FOREIGN KEY/d' /data/oradata/TABLE_ddl.sql #删除外键
sed -i "s/^ALTER TABLE/-- ALTER TABLE/g" /data/oradata/TABLE_ddl.sql #删除主键

导入对象

export LD_LIBRARY_PATH=/app/udbclient/lib PGPASSWORD=$d_w

/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/TABLE_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/FUNCTION_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/GRANT_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/MVIEW_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/PARTITION_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/PROCEDURE_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/VIEW_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/SEQUENCE_ddl.sql;
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/SYNONYM_ddl.sql;

注意: 自定义类型 /data/oradata/TYPE_ddl.sql 语法转换可能会不正确,需要手动处理.可以参考 https://www.sqlines.com/online 网站 进行转换或联系技术支持协助.

此时所有对象已导入目标库中.

导入数据

/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/data.sql

请务必确认此步骤无报错.

导入主键/外键/触发器

/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /tmp/alter.sql 
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /tmp/foreign.sql 
/app/udbclient/ud_sql -v ON_ERROR_STOP=1 -h $d_h -p $d_p -U $d_u -w $d_d -f /data/oradata/TRIGGER_ddl.sql 

此时所有数据已导入目标库中.

开启增量同步,仅当增量同步时操作

export LD_LIBRARY_PATH=/app/udb/lib/:/app/instantclient_19_3/
echo "START REPLICAT repz" > /tmp/3
echo "exit" >> /tmp/3
/app/udb/ggsci paramfile /tmp/3

此时在源端的数据修改操作会同步到目标端.

其它命令

docker exec data2udb /bin/bash -c '/app/scripts/status.sh' #查看增量同步状态
docker exec data2udb /bin/bash -c 'cat /app/udb/dirrpt/REPZ.rpt' #查看增量同步接收报告
docker logs -f data2udb #查看容器日志
docker stop data2udb #停止容器
docker rm data2udb #删除容器
cat /app/udb/ggserr.log #查看目标端增量同步进程日志
cat /app/mysql/ggserr.log #查看源端增量同步进程日志