mysql-schema-sync 之 实例间表结构统一

 

需求:dev,test,release环境由于权限没有统一收管,很容易引起数据库表结构不一致情况;分享一个简单实用易上手的小工具;

mysql-schema-sync:

支持功能:

  1. 同步新表
  2. 同步字段 变动:新增、修改
  3. 同步索引 变动:新增、修改
  4. 支持预览(只对比不同步变动)
  5. 邮件通知变动结果
  6. 支持屏蔽更新表、字段、索引、外键
  7. 支持本地比线上额外多一些表、字段、索引、外键

安装:

go get -u github.com/hidu/mysql-schema-sync

参考 默认配置文件 config.json 配置同步源、目的地址。
修改邮件接收人 当运行失败或者有表结构变化的时候你可以收到邮件通知。

默认情况不会对多出的表、字段、索引、外键删除。若需要删除字段、索引、外键 可以使用 -drop 参数。

配置示例(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: table to check schema,default is all.eg :["order_*","goods"]
      "tables":[],
      //有变动或者失败时,邮件接收人
      "email":{
          "send_mail":false,
         "smtp_host":"smtp.163.com:25",
         "from":"xxx@163.com",
         "password":"xxx",
         "to":"xxx@163.com"
      }
}

json配置项说明

source: 数据库同步源
dest: 待同步的数据库
tables: 数组,配置需要同步的表,为空则是不限制,eg: ["goods","order_*"]
alter_ignore: 忽略修改的配置,表名为tableName,可以配置 column 和 index,支持通配符 *
email : 同步完成后发送邮件通知信息

直接运行

mysql-schema-sync -conf mydb_conf.json -sync

 

预览并生成变更sql

mysql-schema-sync -conf mydb_conf.json 2>/dev/null >db_alter.sql

 

使用shell调度

bash check.sh

 

每个json文件配置一个目的数据库,check.sh脚本会依次运行每份配置。 log存储在当前的log目录中。

自动定时运行

添加crontab 任务

30 * * * * cd /your/path/xxx/ && bash check.sh >/dev/null 2>&1

mysql-schema-sync [-conf] [-dest] [-source] [-sync] [-drop]

说明:

 mysql-schema-sync -help 
# mysql-schema-sync -help  
  -conf string
        配置文件名称
  -dest string
        待同步的数据库 eg: test@(10.10.0.1:3306)/test_1
        该项不为空时,忽略读入 -conf参数项
  -drop
        是否对本地多出的字段和索引进行删除 默认否
  -source string
        mysql 同步源,eg test@(127.0.0.1:3306)/test_0
  -sync
        是否将修改同步到数据库中去,默认否
  -tables string
        待检查同步的数据库表,为空则是全部
        eg : product_base,order_*

参考:https://github.com/hidu/mysql-schema-sync 这种只适合于单个数据库的同步,对于不同实例上百个库的同步来说太过复杂;

上脚本:

(这脚本适用于不同实例之间表结构同步,user 需要有读写权限)

#!/usr/bin/env python
#coding=utf-8


import os 
import json
import pymysql
import sys
 
def get_m_json(filepath,key,value):
    key_ = key.split(".")
    key_length = len(key_)
    with open(filepath, r) as f:
        json_data = json.load(f)
        i = 0
        a = json_data
        while i < key_length :
            if i+1 == key_length :
                a[key_[i]] = "user:pass@("+mysources+":3306)/" + value
                i = i + 1
            else :
                a = a[key_[i]]
                i = i + 1
    f.close()
    return json_data
 
def get_s_json(filepath,key,value):
    key_ = key.split(".")
    key_length = len(key_)
    with open(filepath, r) as f:
        json_data = json.load(f)
        i = 0
        a = json_data
        while i < key_length :
            if i+1 == key_length :
                a[key_[i]] = "usr:pass@("+mydest+":3306)/" + value
                i = i + 1
            else :
                a = a[key_[i]]
                i = i + 1
    f.close()
    return json_data
 
def rewrite_json_file(filepath,json_data):
    with open(filepath, w) as f:
        json.dump(json_data,f)
    f.close()
 
if __name__ == __main__:
    mysources = sys.argv[1]
    mydest = sys.argv[2]
    print (source:+mysources)
    print(dest:+mydest)
    json_path = "/root/go/src/github.com/hidu/mysql-schema-sync/config.json"

    mysqlsync="/usr/bin/mysql-schema-sync"
    print("jsonpath:",json_path)
    conn = pymysql.connect(host=mysources, port=3306, user="user", password="pass", database="information_schema")
    cursor = conn.cursor()
    sql = "select SCHEMA_NAME from SCHEMATA where SCHEMA_NAME not in (‘mysql‘,‘information_schema‘,‘performance_schema‘,‘test‘,‘sys‘);"
    cursor.execute(sql)
    m_dbs = cursor.fetchall()
    cursor.close()
    conn.close()
    print("sourcedbs:",m_dbs)
    conn = pymysql.connect(host=mydest, port=3306, user="user", password="pass", database="information_schema")
    cursor = conn.cursor()
    sql = "select SCHEMA_NAME from SCHEMATA where SCHEMA_NAME not in (‘mysql‘,‘information_schema‘,‘performance_schema‘,‘test‘,‘sys‘);"
    cursor.execute(sql)
    s_dbs = cursor.fetchall()
    cursor.close()
    conn.close()
    print("destdbs:",s_dbs)
    for m_db in m_dbs:
        for s_db in s_dbs:
            if m_db == s_db:
                m_json_data = get_m_json(json_path,"source",m_db[0])
                rewrite_json_file(json_path,m_json_data)
                s_json_data = get_s_json(json_path,"dest",m_db[0])
                rewrite_json_file(json_path,s_json_data)
                sync_cmd = str(mysqlsync)+ -conf +json_path+ -sync 2>/dev/null >> +mysources.split(.)[0]+_to_+mydest.split(.)[0]+_+m_db[0]+.sql
                os.system(sync_cmd)
                sync_cmd1 = str(mysqlsync)+ -conf +json_path+ -sync 2>/dev/null >>sync.log 
                print(sync_cmd1)
                os.system(sync_cmd1)
                break 

 

mysql-schema-sync 之 实例间表结构统一

上一篇:sqlserver 直接清除 ldf文件 释放磁盘空间


下一篇:postgresql-10.12安装和部署