共计 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 问一下细节