Mysql表结构自动同步工具mysql-schema-sync

高晋
2023-12-01

平时在工作中会遇到某个测试环境服务正常,其它测试环境不可用,通过日志排查数据库表不存在或者表字段不存在,偶尔一两次手动同步还可以接受,但是当服务较多、快速迭代时会经常出现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地址

 类似资料: