平时在工作中会遇到某个测试环境服务正常,其它测试环境不可用,通过日志排查数据库表不存在或者表字段不存在,偶尔一两次手动同步还可以接受,但是当服务较多、快速迭代时会经常出现xxx上线后忘记同步测试环境数据库的时候,影响效率而且内心难以接受。
于是为了解决这个问题在网上搜索了一番,发现大佬使用 Go 语言开源了表结构同步工具 mysql-schema-sync ,使用文档也非常详细,接下来看看这款工具都有哪些功能以及如何使用。
mysql-schema-sync 是一款使用 Go 开发跨平台的 MySQL 表结构自动同步工具。主要用于解决多个环境数据库表结构不同步问题。
mysql-schema-sync 支持功能:
同步新表
同步字段 变动:新增、修改
同步索引 变动:新增、修改
支持预览(只对比不同步变动)
邮件通知变动结果
支持屏蔽更新表、字段、索引、外键
支持本地比线上额外多一些表、字段、索引、外键
Go环境安装
1、下载go安装包:下载地址1 、下载地址2
2、安装以及配置环境变量
# 1、选择一个go放置的目录进行解压
tar -C /user/local -xzf go1.14.6.darwin-amd64.tar.gz
# 2、解压完成之后配置go环境变量
# 编辑~/.bash_profile文件
vim ~/.bash_profile
# 在~/.bash_profile文件中添加以下2条命令
export GOROOT=/user/local/go
export PATH=$PATH:$GOROOT/bin
# 使配置生效
localhost:~ zxy$ sorce ~/.bash_profile
3、验证,通过命令go version可以直接查看到版本号说明安装成功
安装mysql-schema-sync,可以把源码下载下来自己编译也可以直接使用下面的命令进行安装
go get -u github.com/hidu/mysql-schema-sync
使用说明
1、config配置文件(config.json)说明
{
//source:同步源
"source":"test:test@(127.0.0.1:3306)/test_0",
//dest:待同步的数据库
"dest":"test:test@(127.0.0.1:3306)/test_1",
// alter_ignore: 同步时忽略的字段和索引
"alter_ignore":{
"tb1*":{
"column":["aaa","a*"],
"index":["aa"],
"foreign":[]
}
},
// tables 默认同步所有的表
"tables":[],
// 有变动或者失败时,邮件接收人
"email":{
"send_mail":false,
"smtp_host":"smtp.163.com:25",
"from":"xxx@163.com",
"password":"xxx",
"to":"xxx@163.com"
}
}
2、运行命令
mysql-schema-sync -conf config.json -sync
3、参数说明
基本格式:mysql-schema-sync [-conf] [-dest] [-source] [-sync] [-drop]
-conf string 配置文件名称
-dest string 待同步的数据库,该项不为空时,忽略读入 -conf参数项
-drop 是否对本地多出的字段和索引进行删除 默认否
-source string mysql 同步源
-sync 是否将修改同步到数据库中去,默认否
-tables string 待检查同步的数据库表,为空则是全部
当有很多数据库需要同步时,创建对应数量的配置文件然后编写脚本循环执行也可以,但是创建文件时特别耗时,尝试了以下两种方式:
1、动态替换配置文件中的源数据库和目标数据库,这样就需要频繁的修改文件
2、通过命令行把源数据库和目标数据库传进去,正如参数说明里面描述的,待同步数据库不为空忽略读入配置文件
由于我选择的是第二种方式,所以稍微修改源码支持传入数据并且读取配置文件,工作中有以数据库实例区分环境和以数据库区分环境两种方式,在编写脚本的时候稍微有点差别。
3、脚本及相关文件说明
使用数据库区分环境,testdb1.txt里面只存放数据库名
mydb2 mydb1
mydb3 mydb1
使用数据库实例区分环境,testdb.txt里面只存放数据库名
mydb1
mydb2
mysql.txt里面存放数据库ip,最后一行是通过数据库区分环境的情况
10.0.0.1 10.0.0.0
10.0.0.2 10.0.0.0
10.1.0.0 10.1.0.0
#!/bin/bash
###########################
# mysql.sh
# 核心思想,先把所有环境的变动同步到一个环境,再把该环境同步到其它环境
###########################
# 保存IP
i=2
array=()
# 保存db
j=1
ad_arr=()
# 统计文件行数
function count(){
wc -l $1 | awk '{print $1}'
}
# 循环读取数据库名
function db_fun() {
cat $1 | while read line
do
read source_db target_db <<< `echo $line | awk '{print $1,$2}'`
if [ $2 == $3 ];then
echo "mysql://$2:3306/${source_db} mysql://$3:3306/${target_db}"
db_arr[$j]=${source_db}
let j+=1
num=`count $1`
if [ $j -gt $num ]; then
for db_new in ${db_arr[@]}
do
echo "mysql://$2:3306/${target_db} mysql://$3:3306/${db_new}"
done
fi
else
echo "mysql://$2:3306/$line myysql://$3:3306/$line"
fi
done
}
# 循环读取数据库IP
function ip_fun(){
cat $1 | while read line
do
read source target <<< `echo $line | awk '{print $1,$2}'`
if [ "$source" == "$target" ];then
db_fun testdb1.txt $source $target
else
db_fun testdb.txt $source $target
array[$i]=$source
let i+=1
num=`count $1`
if [ $i -gt $num ]; then
for target_new in ${array[@]}
do
db_fun testdb.txt $target $target_new
done
fi
fi
done
}
ip_fun mysql.txt
4、定时任务配置
0 8 * * * /home/worker/nysql.sh
到此自动化同步mysql表结构就完成了,感谢大佬的开源,希望对大家有一定的帮助。
mysql-schema-sync的git地址