Mysql同步YashanDB实战
YashanDB作为一个最近热度挺高的一款国产数据库,推出了个人版体验。但是个人版有没提供数据同步工具,花了俩周末自己用GO写了个工具同步可以实现mysql数据(包含元数据和表数据)同步到yashandb,底层调用了YashanDB C驱动,对于数据同步常用的场景感觉够用了。
工具名称:mysql2yasdb,下载地址:https://gitee.com/liang-xiong888/mysql2yasdb。大家可以按需下载测试,有什么问题和建议欢迎随时交流。
环境信息:MySQL用的是8.0的,YashanDB用的个人版。
1. 安装YashanDB
1.1 下载YashanDB安装包
1.2 通过yasboot安装YashanDB
-
解压压缩包到yashandb_home路径
-
进入bin目录使用yasboot命令来安装数据库首先生成部署集群配置文件:
./yasboot package config gen --cluster lx --yas-type se --ip 192.168.80.100 --username lx --password xxxxx --port 22 --install-path /home/lx/install_yashandb/
- –cluster 参数制定将要部署的数据库名称
- –yas-type 参数制定部署的数据库类型
- –ip 参数指定数据库即将部署到的主机ip
- –username 指定数据库部署到那个用户下
- –password 指定该用户的密码
- –port 指定ssh连接的端口
- –install-path 指定数据库即将被安装到那个目录
-
命令执行完后自动展示生成数据库配置:
-
查看当前目录会生成两个配置文件
- lx.toml:保存了数据库节点配置信息
- host.toml:主机的信息,之后package install会用到
-
-
进行安装包的上传
./yasboot package install --install-pkg ../../yashandb/yashandb-personal-23.1.1.100-linux-x86_64.tar.gz --toml hosts.toml
- –install-pkg指定本地安装包的路径(用于上传到指定服务器)
- –toml:指定主机的配置信息,前一步package config gen生成的
-
进行数据库部署
./yasboot cluster deploy --toml ./lx.toml
- –toml: 指定部署数据库的配置文件,前面package config gen生成的
-
设置密码
./yasboot cluster password set -n Lx-password1 -c lx
-
当看到success后数据库,部署成功,现在验证数据库是否可以连接
-
数据库安装路径
/home/lx/install_yashandb/yashandb/23.1.1.100/conf
有个环境变量信息lx.bashrc -
执行进入该目录执行
source lx.bashrc
使环境变量生效 -
通过
yasql sys/Lx-password1
登录数据库,查看v$isntance
试图数据库是否能够连接
-
2. 迁移数据到yashandb
2.1 mysql2yasdb脚本简介
-
**读取MySQL数据库内的对象生产YashanDB的元数据创建SQL。**目前只支持表,约束,默认值,自增序列,主键,外键,普通索引,视图。
-
**将MySQL数据库内的表数据迁移到YashanDB中。**支持以表模式、库模式迁移。支持模式对应、并行迁移、批量处理、指定排除表、指定表的过滤条件等配置参数
-
下载链接:mysql2yasdb
2.2 mysql2yasdb脚本使用说明
-
数据库用户权限:用于连接MySQL数据库的用户,需要授予如下MySQL系统表的查询权限
information_schema.tables information_schema.columns information_schema.key_column_usage information_schema.views information_schema.triggers
-
设置环境变量
export MYSQL2YASDB_HOME=/xx/yy/mysql2yasdb ----工具包mysql2yasdb-xxxx-linux-x86_64.tar.gz解压后的根目录mysql2yasdb-xxxx,根据部署环境提供真实路径 export PATH=$PATH:$MYSQL2YASDB_HOME export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MYSQL2YASDB_HOME/lib ${MYSQL2YASDB_HOME}为工具包解压后的根目录
工具依赖于如下lib包,如果工具运行过程中报lib包相关错误,可使用与目标库YashanDB版本匹配的lib文件进行替换。
libyascli.so libyas_infra.so.0 libcrypto.so.1.1 libzstd.so.1
-
工具使用帮助
全局选项: -h, --help 显示帮助信息 -v, --version 显示程序版本号 -c, --config 指定DB配置信息文件 -d, --data 仅同步表数据,此参数开启时,不生成ddl文件 ●用法示例1: 直接执行,使用当前目录下的db.ini配置文件获取程序运行时的配置信息,导出对象ddl,ddl导出文件分被位于tables_ddl,others_ddl ./mysql2yasdb ●用法示例2: 使用自定义配置文件xxx.ini,导出对象ddl ./mysql2yasdb -c xxx.toml 或 ./mysql2yasdb --config=xxx.toml ●用法示例3: 使用当前目录下的db.toml配置文件,并进行表数据的同步,但不生成ddl文件 ./mysql2yasdb -d
-
配置文件说明:mysql2yasdb解压目录下db.toml文件为工具参数配置文件,其中参数说明如下
[mysql] host="192.168.xx.xx" #mysql主机IP地址 port=3306 #mysql访问端口 database="test" #默认访问的database,当按tables导出时,导出此database下面的表 username="yashan" #mysql访问用户名,需授予information_schema下相关系统表访问权限 password="yashan123" #mysql访问用户密码 #tables=["table1","table2"] #需迁移的mysql表名称,和参数schemas不能同时配置 schemas=["db1","db2","db3"] #需迁移的databases的名称,和参数tables不能同时配置 #exclude_tables=table3,table4 #迁移过程中需排除的表名称,schemas配置多个时,多个schemas下面的此名称的表都不导出/数据同步 #parallel=1 #并发度,值为N时表示同时并发迁移N个表,表较多时建议加大此参数可以提升速度,默认值1,取值范围[1-8] #parallel_per_table=1 #表内并行度,值为N时表示同一张表开启N个并行同步数据,表较大时建议加大此参数可以提升,默认值1,取值范围[1-8] #batchSize=1000 #批次大小,值为N时表示一次事务处理N行数据,默认值1000 #query="where create_date < '2022-01-11 00:00:00'" #设置查询条件,会对所有要同步的表都加上此条件 [yashandb] host="192.168.xx.xx" #YahsanDB主机IP地址 port=1688 #YashanDB访问端口 username="yashan" #YashanDB访问用户名,按表导入时,导入到此用户下 password="yashan123" #YashanDB访问用户密码 remap_schemas=["yashan","yashan","yashan"] #迁移至YashanDB的目标用户名称,当和参数schemas一起配置时,它的值需要和参数schemas的值一一对应,schemas第N个值对应到remap_schemas第N个值。当和tables一起配置时,只取remap_schemas的第一个值, 当想要将yashandb用户定义为小写的时候需要时用反引号包裹, e.g:`"user1","user2"`
2.4 mysql2yasdb实战
2.4.1 创建mysql数据源
我是使用docker启动的mysql,大家也可以使用存在的任一mysql数据库作为数据源
-
使用docker启动mysql
# 拉取mysql镜像 docker pull mysql # 启动mysql docker run --name test-mysql2yasdb -e MYSQL_ROOT_PASSWORD=your_password -p 3306:3306 -d mysql # 查看mysql容器状态 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c0fe5d2d3de9 mysql "docker-entrypoint.s…" 55 seconds ago Up 54 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp test-mysql2yasdb
-
登录容器
docker exec -it test-mysql2yasdb bash
-
进入后创建数据库对象
-- 创建数据库 CREATE DATABASE IF NOT EXISTS test_db DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 使用数据库 USE test_db; -- 创建表1 CREATE TABLE IF NOT EXISTS table1 ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, age TINYINT UNSIGNED NOT NULL, gender ENUM('male', 'female') DEFAULT 'male' COMMENT '性别', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); -- 创建表2 CREATE TABLE IF NOT EXISTS table2 ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, table1_id INT UNSIGNED NOT NULL, name VARCHAR(50) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (table1_id) REFERENCES table1(id) ); -- 创建表3 CREATE TABLE IF NOT EXISTS table3 ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, table1_id INT UNSIGNED NOT NULL, name VARCHAR(50) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_table1_id (table1_id), FOREIGN KEY (table1_id) REFERENCES table1(id) ); -- 创建视图 CREATE VIEW view1 AS SELECT t1.id, t1.name, t2.name AS table2_name, t3.name AS table3_name FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.table1_id LEFT JOIN table3 t3 ON t1.id = t3.table1_id; -- 插入数据 INSERT INTO table1 (name, age) VALUES ('Alice', 20), ('Bob', 22), ('Charlie', 25); INSERT INTO table2 (table1_id, name) VALUES (1, 'Table2 - 1'), (2, 'Table2 - 2'); INSERT INTO table3 (table1_id, name) VALUES (1, 'Table3 - 1'), (3, 'Table3 - 2'); -- 查询数据 SELECT * FROM table1; SELECT * FROM table2; SELECT * FROM table3; SELECT * FROM view1;
2.4.2 配置mysql2yasdb
-
解压mysql2yasdb
tar -zxvf mysql2yasdb-1.6.3-linux-x86_64.tar.gz
-
进入解压目录
# 查看目录文件 [lx@worker248 mysql2yasdb-1.6.3]$ ll total 13588 -rw-rw-r-- 1 lx lx 429 Nov 6 14:43 db.toml drwxr-xr-x 2 lx lx 95 Nov 6 14:43 lib -rwxrwxr-x 1 lx lx 13901416 Nov 6 14:43 mysql2yasdb -rw-rw-r-- 1 lx lx 4525 Nov 6 14:43 README.md
-
配置环境变量
export MYSQL2YASDB_HOME=$(pwd) export PATH=$PATH:$MYSQL2YASDB_HOME export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MYSQL2YASDB_HOME/lib
2.4.3 schema级别同步示例
-
配置db.toml
[mysql] host="192.168.xx.xx" # 这里更改为实际mysql源端ip port=3306 database="test_db" username="root" password="your_password" schemas=["test_db"] [yashandb] host="192.168.xx.xx" # 这里实际更改为实际yashan目标端ip port=1688 username="sys" password="Lx-password1" remap_schemas=["test_db"]
-
生成DDL
# 执行mysql2yasdb默认生成DDL mysql2yasdb
执行结果如下
[lx@worker248 mysql2yasdb-1.6.3]$ mysql2yasdb 2023-11-30 11:22:40 INFO mysql2yasdb/mysql2yasdb.go:1674 ddl文件生成完成。
-
查看生成的文件
默认会在当前目录生成两个文件夹
- tables_ddl:包含table定义的DDL文件
- others_ddl:包含约束,索引,视图的DDL文件
生成结果如下:
[lx@worker248 mysql2yasdb-1.6.3]$ tree . ├── db.toml ├── lib │ ├── libcrypto.so.1.1 │ ├── libyascli.so │ ├── libyas_infra.so.0 │ └── libzstd.so.1 ├── log │ └── console.log ├── mysql2yasdb ├── others_ddl │ └── test_db_others.sql ├── README.md └── tables_ddl └── test_db_tables.sql
-
使用yasql进入yashandb创建test_db数据库,赋予权限
create user test_db identified by test; grant dba to test_db;
执行结果如下:
[lx@worker248 mysql2yasdb-1.6.3]$ yasql sys/Lx-password1 YashanDB SQL Personal Edition Release 23.1.1.100 x86_64 Connected to: YashanDB Server Personal Edition Release 23.1.1.100 x86_64 - X86 64bit Linux SQL> create user test_db identified by test; Succeed. SQL> grant dba to test_db; Succeed. SQL>
-
使用yasql -f 命令将导出文件执行导入数据库
yasql sys/Lx-password1 -f tables_ddl/test_db_tables.sql yasql sys/Lx-password1 -f others_ddl/test_db_others.sql
执行结果如下(可见元数据完全导入):
[lx@worker248 mysql2yasdb-1.6.3]$ yasql sys/Lx-password1 -f tables_ddl/test_db_tables.sql Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. [lx@worker248 mysql2yasdb-1.6.3]$ yasql sys/Lx-password1 -f others_ddl/test_db_others.sql Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed. Succeed.
-
验证导入结果:
# 验证表 select object_name from dba_objects where object_type='TABLE' AND OWNER='TEST_DB'; # 验证视图 select object_name from dba_objects where object_type='VIEW' AND OWNER='TEST_DB';
执行结果如下:
SQL> select object_name from dba_objects where object_type='TABLE' AND OWNER='TEST_DB'; OBJECT_NAME ---------------------------------------------------------------- TABLE1 TABLE2 TABLE3 3 rows fetched. SQL> select object_name from dba_objects where object_type='VIEW' AND OWNER='TEST_DB'; OBJECT_NAME ---------------------------------------------------------------- VIEW1 1 row fetched. SQL>
-
执行数据导入
mysql2yasdb -d
执行结果:
[lx@worker248 mysql2yasdb-1.6.3]$ mysql2yasdb -d 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1647 本次数据同步多表并发度为: 1 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1648 本次数据同步表内并行度为: 1 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1649 本次数据同步批处理大小为: 1 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1337 table1开始同步 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1367 table1 处理完成,迁移数据量: 3 耗时 12.190306ms 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1337 table2开始同步 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1367 table2 处理完成,迁移数据量: 2 耗时 10.036692ms 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1337 table3开始同步 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:1367 table3 处理完成,迁移数据量: 2 耗时 8.433669ms 2023-11-30 11:45:52 INFO mysql2yasdb/mysql2yasdb.go:943 任务完成,共耗时: 85.74994ms
-
验证数据同步结果:
查看MySQL数据:
mysql> use test_db; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> SELECT * FROM table1; +----+---------+-----+--------+---------------------+---------------------+ | id | name | age | gender | created_at | updated_at | +----+---------+-----+--------+---------------------+---------------------+ | 1 | Alice | 20 | male | 2023-11-30 02:47:36 | 2023-11-30 02:47:36 | | 2 | Bob | 22 | male | 2023-11-30 02:47:36 | 2023-11-30 02:47:36 | | 3 | Charlie | 25 | male | 2023-11-30 02:47:36 | 2023-11-30 02:47:36 | +----+---------+-----+--------+---------------------+---------------------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM table2; +----+-----------+------------+---------------------+---------------------+ | id | table1_id | name | created_at | updated_at | +----+-----------+------------+---------------------+---------------------+ | 1 | 1 | Table2 - 1 | 2023-11-30 02:47:36 | 2023-11-30 02:47:36 | | 2 | 2 | Table2 - 2 | 2023-11-30 02:47:36 | 2023-11-30 02:47:36 | +----+-----------+------------+---------------------+---------------------+ 2 rows in set (0.01 sec) mysql> SELECT * FROM table3; +----+-----------+------------+---------------------+---------------------+ | id | table1_id | name | created_at | updated_at | +----+-----------+------------+---------------------+---------------------+ | 1 | 1 | Table3 - 1 | 2023-11-30 02:47:37 | 2023-11-30 02:47:37 | | 2 | 3 | Table3 - 2 | 2023-11-30 02:47:37 | 2023-11-30 02:47:37 | +----+-----------+------------+---------------------+---------------------+ 2 rows in set (0.00 sec) mysql>
查看yashandb的数据
# 使用test_db登录数据库 yasql test_db/test # 执行查询 SELECT * FROM table1; SELECT * FROM table2; SELECT * FROM table3;
查看结果:
至此,使用mysql2yasdb成功将mysql数据同步到了yashandb。
个人感受
- 选择GO语言编程,是因为简单易用,与C的适配做的比较好,跨平台性做的比较好,写出来的工具也可以开箱即用。代码量不多,一两千行。
- mysql到yashandb同步主要适配点是数据类型的映射,因为yashandb语法上主要是跟Oracle兼容, 与mysql还是有不少差异,所以做了个类型映射花了点时间。