使用golang怎么实现mysql数据库备份

62次阅读
没有评论

共计 4849 个字符,预计需要花费 13 分钟才能阅读完成。

自动写代码机器人,免费开通

这期内容当中丸趣 TV 小编将会给大家带来有关使用 golang 怎么实现 mysql 数据库备份,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

map json,在处理主键与外键信息时,需要用到 json 数据结构来存储中间结果,因为要灵活处理,在 golang 中只能用 map[string]interface{} 来处理。

interface{} 相当于 java 中的 object,能接受任意数据类型,方便但在使用时要做到心中有数,不然一旦数据类型不匹配,程序就会崩溃。

xfffd,utf8 中的占位符,超出范围的 utf8mb4 入库后,会被存储为 xfffd,数据导出时,需要过滤掉。

goroutine,golang 的并发支持很独特,我们的工具支持多个库同时备份,很容易使用 goroutine 来实现并行。

代码解析

按功能模块对核心代码进行说明

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].(float64)),
 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 的优点

golang 是一种编译语言,可以将代码编译为机器代码,编译后的二进制文件可以直接部署到目标机器而无需额外的依赖,所以 golang 的性能优于其他的解释性语言,且可以在 golang 中使用 goroutine 来实现并发性,它提供了一个非常优雅的 goroutine 调度程序系统,可以很容易地生成数百万个 goroutine。

上述就是丸趣 TV 小编为大家分享的使用 golang 怎么实现 mysql 数据库备份了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注丸趣 TV 行业资讯频道。

向 AI 问一下细节

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-04发表,共计4849字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)