背景
navicat是mysql可视化工具中最棒的,但是,在处理视图的导入导出方面,它是按照视图名称的字母顺序来处理的,若视图存在依赖,在导入过程中就会报错。前面已经用python写了一个,但在使用过程中,遇到xfffd编码,python的pymysql会直接崩溃。发现golang没有这个问题,正好用go重写,来熟悉golang。
一些关键点
代码解析
按功能模块对核心代码进行说明
main.go,并发、命令行参数
使用命令行参数,接受一个参数,来指定备份的内容
package common
type OpFlag struct {
 Tables bool //表结构
 Datum bool //表结构和数据
 Views bool //视图
 Funcs bool //函数与存储过程
}
main.go,程序入口,处理命令行参数
 if len(os.Args) > 1 {
 flag = common.OpFlag{
 Tables: false,
 Datum: false,
 Views: false,
 Funcs: false,
 }
 switch os.Args[1] { //接受一个参数
 case "table":
 flag.Tables = true //根据参数设定标识量
 case "data":
 flag.Tables = true
 flag.Datum = true
 case "views":
 flag.Views = true
 case "funcs":
 flag.Funcs = true
 default: //参数不正确,报错退出
 log.Fatal("You arg must be in : table, data, views or funcs.")
 }
 }else{ //无参数,默认导出所有
 flag = common.OpFlag{
 Tables: true,
 Datum: true,
 Views: true,
 Funcs: true,
 }
 }
 err := backUp.Export(flag) 根据参数进行数据库备份
Export.go
备份主流程,根据configs.json生成goroutine来备份数据库,并等待完成。
var configs interface{}
 fr, err := os.Open("./configs.json")
 if err != nil {
 return err
 }
 decoder := json.NewDecoder(fr) //解析配置文件
 err = decoder.Decode(&configs)
 confs := configs.(map[string]interface{})
 workDir := confs["workDir"].(string)
 ch := make(chan string) //通道变量
 for key, value := range confs {
 if strings.HasPrefix(key, "db_") {
 dbConf := value.(map[string]interface{})
 dbConn := common.DbConnFields{ //数据库相应配置
 DbHost: dbConf["db_host"].(string),
 DbPort: int(dbConf["db_port"].(float)),
 DbUser: dbConf["db_user"].(string),
 DbPass: dbConf["db_pass"].(string),
 DbName: dbConf["db_name"].(string),
 DbCharset: dbConf["db_charset"].(string),
 }
 if dbConf["file_alias"] != nil { //生成sql备份文件的命名
 dbConn.FileAlias = dbConf["file_alias"].(string)
 }
 go ExportOne(dbConn, workDir, ch, flag) //创建协程
 }
 }
 for key := range confs { //阻塞主进程,待所有协程完成工作
 if strings.HasPrefix(key, "db_") {
 fmt.Print( <- ch )
 }
 }
 return nil
你需要编写如下的配置文件来描述你要备份的数据库:
{
 "db_name1": {
 "db_host": "192.168.1.8",
 "db_port": 3306,
 "db_user": "root",
 "db_pass": "123456",
 "db_name": "name1",
 "db_charset": "utf8mb4",
 "file_alias": "file name1"
 },
 "db_name2": {
 "db_host": "localhost",
 "db_port": 3306,
 "db_user": "root",
 "db_pass": "123456",
 "db_name": "name2",
 "db_charset": "utf8mb4"
 },
 "database_dialect": "mysql",
 "workDir": "/home/zhoutk/gocodes/goTools/"
}
ExportOne.go
备份一个数据库       
fileName := fields.FileAlias
 setSqlHeader(fields, fileName) //设置导出文件说明
 if flag.Tables { //如果表设置为真,导出表结构
 err := exportTables(fileName, fields, flag) //具体算法请参照源代码
 if err != nil {
 ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export tables throw, \t", err)
 return
 }
 }
 if flag.Views { //如果视图设置为真,导出视图
 err := exportViews(fileName, fields)//具体算法请参照源代码,或python算法
 if err != nil {
 ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export views throw, \t", err)
 return
 }
 }
 if flag.Funcs { //如果函数设置为真,导出函数和存储过程
 err := exportFuncs(fileName, fields)//具体算法请参照源代码
 if err != nil {
 ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export funcs throw, \t", err)
 return
 }
 }
 //导出工作完成,向通道输入信息
 ch <- fmt.Sprintln("Export ", fields.DbName, "\t success at \t", time.Now().Format("2006-01-02 15:04:05")) 
MysqlDao.go
数据库查询通用封装,此工具只使用了ExecuteWithDbConn。灵活的使用map与interface{},将结果转化为键值对象返回。
func ExecuteWithDbConn(sql string, values []interface{}, fields common.DbConnFields) (map[string]interface{}, error) {
 rs := make(map[string]interface{})
 dao, err := mysql.Open("mysql", fields.DbUser + ":"+fields.DbPass+"@tcp("+fields.DbHost+":"+
 strconv.Itoa(fields.DbPort)+")/"+fields.DbName+"?charset="+fields.DbCharset)
 defer dao.Close()
 if err != nil {
 rs["code"] = 204
 return rs, err
 }
 stmt, err := dao.Prepare(sql)
 if err != nil {
 rs["code"] = 204
 return rs, err
 }
 rows, err := stmt.Query(values...)
 if err != nil {
 rs["code"] = 204
 return rs, err
 }
 columns, err := rows.Columns() //取出字段名称
 vs := make([]mysql.RawBytes, len(columns))
 scans := make([]interface{}, len(columns))
 for i := range vs { //预设取值地址
 scans[i] = &vs[i]
 }
 var result []map[string]interface{}
 for rows.Next() {
 _ = rows.Scan(scans...) //塡入一列值
 each := make(map[string]interface{})
 for i, col := range vs {
 if col != nil {
 each[columns[i]] = FilterHolder(string(col)) //过滤/xfffd
 }else{
 each[columns[i]] = nil
 }
 }
 result = append(result, each)
 }
 rs["code"] = 200
 //data, _ := json.Marshal(result)
 rs["rows"] = result
 return rs, err
}
项目地址
https://github.com/zhoutk/goTools
使用方法
git clone https://github.com/zhoutk/goTools cd goTools go get go run main.go go buid main.go ./main #export all things of database ./main table #export tables ./main data #export tables & data ./main views #export views ./main funcs #export funcs & stored procedures
总结
以上所述是小编给大家介绍的golang实现mysql数据库备份的操作方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!