• 售前

  • 售后

热门帖子
入门百科

golang实现mysql数据库备份的操纵方法

[复制链接]
真无牙泛 显示全部楼层 发表于 2021-10-26 12:42:45 |阅读模式 打印 上一主题 下一主题
背景
navicat是mysql可视化工具中最棒的,但是,在处置处罚视图的导入导出方面,它是按照视图名称的字母次序来处置处罚的,若视图存在依赖,在导入过程中就会报错。前面已经用python写了一个,但在使用过程中,碰到xfffd编码,python的pymysql会直接瓦解。发现golang没有这个问题,正好用go重写,来认识golang。
一些关键点
      
  • map & json,在处置处罚主键与外键信息时,须要用到json数据结构来存储中间结果,由于要机动处置处罚,在golang中只能用map[string]interface{}来处置处罚。  
  • interface{} 相称于java中的object,能担当恣意数据类型,方便但在使用时要做到心中有数,不然一旦数据类型不匹配,步伐就会瓦解。  
  • xfffd ,utf8中的占位符,超出范围的utf8mb4入库后,会被存储为xfffd,数据导出时,须要过滤掉。  
  • goroutine, golang的并发支持很独特,我们的工具支持多个库同时备份,很轻易使用goroutine来实现并行。
代码解析
按功能模块对核心代码举行阐明
main.go,并发、下令行参数
使用下令行参数,担当一个参数,来指定备份的内容
package common
  1. type OpFlag struct {
  2.   Tables bool      //表结构
  3.   Datum bool       //表结构和数据
  4.   Views bool       //视图
  5.   Funcs bool       //函数与存储过程
  6. }
复制代码
main.go,步伐入口,处置处罚下令行参数  
  1. if len(os.Args) > 1 {
  2.     flag = common.OpFlag{
  3.       Tables: false,
  4.       Datum: false,
  5.       Views: false,
  6.       Funcs: false,
  7.     }
  8.     switch os.Args[1] {     //接受一个参数
  9.     case "table":
  10.       flag.Tables = true    //根据参数设定标识量
  11.     case "data":
  12.       flag.Tables = true
  13.       flag.Datum = true
  14.     case "views":
  15.       flag.Views = true
  16.     case "funcs":
  17.       flag.Funcs = true
  18.     default:          //参数不正确,报错退出
  19.       log.Fatal("You arg must be in : table, data, views or funcs.")
  20.     }
  21.   }else{            //无参数,默认导出所有
  22.     flag = common.OpFlag{
  23.       Tables: true,
  24.       Datum: true,
  25.       Views: true,
  26.       Funcs: true,
  27.     }
  28.   }
  29.   err := backUp.Export(flag) 根据参数进行数据库备份
复制代码
Export.go
备份主流程,根据configs.json生成goroutine来备份数据库,并等候完成。
  1. var configs interface{}
  2.   fr, err := os.Open("./configs.json")
  3.   if err != nil {
  4.     return err
  5.   }
  6.   decoder := json.NewDecoder(fr)         //解析配置文件
  7.   err = decoder.Decode(&configs)
  8.   confs := configs.(map[string]interface{})
  9.   workDir := confs["workDir"].(string)
  10.   ch := make(chan string)            //通道变量
  11.   for key, value := range confs {
  12.     if strings.HasPrefix(key, "db_") {
  13.       dbConf := value.(map[string]interface{})
  14.       dbConn := common.DbConnFields{   //数据库相应配置
  15.         DbHost:  dbConf["db_host"].(string),
  16.         DbPort:  int(dbConf["db_port"].(float64)),
  17.         DbUser:  dbConf["db_user"].(string),
  18.         DbPass:  dbConf["db_pass"].(string),
  19.         DbName:  dbConf["db_name"].(string),
  20.         DbCharset: dbConf["db_charset"].(string),
  21.       }
  22.       if dbConf["file_alias"] != nil {  //生成sql备份文件的命名
  23.         dbConn.FileAlias = dbConf["file_alias"].(string)
  24.       }
  25.       go ExportOne(dbConn, workDir, ch, flag) //创建协程
  26.     }
  27.   }
  28.   for key := range confs {            //阻塞主进程,待所有协程完成工作
  29.     if strings.HasPrefix(key, "db_") {
  30.       fmt.Print( <- ch )
  31.     }
  32.   }
  33.   return nil
复制代码
你须要编写如下的设置文件来形貌你要备份的数据库:
  1. {
  2.   "db_name1": {
  3.     "db_host": "192.168.1.8",
  4.     "db_port": 3306,
  5.     "db_user": "root",
  6.     "db_pass": "123456",
  7.     "db_name": "name1",
  8.     "db_charset": "utf8mb4",
  9.     "file_alias": "file name1"
  10.   },
  11.   "db_name2": {
  12.     "db_host": "localhost",
  13.     "db_port": 3306,
  14.     "db_user": "root",
  15.     "db_pass": "123456",
  16.     "db_name": "name2",
  17.     "db_charset": "utf8mb4"
  18.   },
  19.   "database_dialect": "mysql",
  20.   "workDir": "/home/zhoutk/gocodes/goTools/"
  21. }
复制代码
ExportOne.go
备份一个数据库      
  1. fileName := fields.FileAlias
  2.   setSqlHeader(fields, fileName)      //设置导出文件说明
  3.   if flag.Tables {            //如果表设置为真,导出表结构
  4.     err := exportTables(fileName, fields, flag)  //具体算法请参照源代码
  5.     if err != nil {
  6.       ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export tables throw, \t", err)
  7.       return
  8.     }
  9.   }
  10.   if flag.Views {            //如果视图设置为真,导出视图
  11.     err := exportViews(fileName, fields)//具体算法请参照源代码,或python算法
  12.     if err != nil {
  13.       ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export views throw, \t", err)
  14.       return
  15.     }
  16.   }
  17.   if flag.Funcs {        //如果函数设置为真,导出函数和存储过程
  18.     err := exportFuncs(fileName, fields)//具体算法请参照源代码
  19.     if err != nil {
  20.       ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export funcs throw, \t", err)
  21.       return
  22.     }
  23.   }
  24.   //导出工作完成,向通道输入信息
  25.   ch <- fmt.Sprintln("Export ", fields.DbName, "\t success at \t", time.Now().Format("2006-01-02 15:04:05"))  
复制代码
MysqlDao.go
数据库查询通用封装,此工具只使用了ExecuteWithDbConn。机动的使用map与interface{},将结果转化为键值对象返回。
  1. func ExecuteWithDbConn(sql string, values []interface{}, fields common.DbConnFields) (map[string]interface{}, error) {
  2.   rs := make(map[string]interface{})
  3.   dao, err := mysql.Open("mysql", fields.DbUser + ":"+fields.DbPass+"@tcp("+fields.DbHost+":"+
  4.     strconv.Itoa(fields.DbPort)+")/"+fields.DbName+"?charset="+fields.DbCharset)
  5.   defer dao.Close()
  6.   if err != nil {
  7.     rs["code"] = 204
  8.     return rs, err
  9.   }
  10.   stmt, err := dao.Prepare(sql)
  11.   if err != nil {
  12.     rs["code"] = 204
  13.     return rs, err
  14.   }
  15.   rows, err := stmt.Query(values...)
  16.   if err != nil {
  17.     rs["code"] = 204
  18.     return rs, err
  19.   }
  20.   columns, err := rows.Columns()    //取出字段名称
  21.   vs := make([]mysql.RawBytes, len(columns))
  22.   scans := make([]interface{}, len(columns))
  23.   for i := range vs {         //预设取值地址
  24.     scans[i] = &vs[i]
  25.   }
  26.   var result []map[string]interface{}
  27.   for rows.Next() {
  28.     _ = rows.Scan(scans...)    //塡入一列值
  29.     each := make(map[string]interface{})
  30.     for i, col := range vs {
  31.       if col != nil {
  32.         each[columns[i]] = FilterHolder(string(col)) //过滤/xfffd
  33.       }else{
  34.         each[columns[i]] = nil
  35.       }
  36.     }
  37.     result = append(result, each)
  38.   }
  39.   rs["code"] = 200
  40.   //data, _ := json.Marshal(result)
  41.   rs["rows"] = result
  42.   return rs, err
  43. }
复制代码
项目地址
https://github.com/zhoutk/goTools
使用方法
  1. git clone https://github.com/zhoutk/goTools
  2. cd goTools
  3. go get
  4. go run main.go
  5. go buid main.go
  6. ./main         #export all things of database
  7. ./main table      #export tables
  8. ./main data       #export tables & data
  9. ./main views      #export views
  10. ./main funcs      #export funcs & stored procedures
复制代码
总结
以上所述是小编给大家先容的golang实现mysql数据库备份的利用方法,盼望对大家有所资助,如果大家有任何疑问请给我留言,小编会实时复兴大家的。在此也非常感谢大家对草根技术分享网站的支持!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作