原标题:golang 实现 mysql 数据库备份

背景

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。

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(

}

}

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

return

}

}

if flag.Views { //如果视图设置为真,导出视图

err := exportViews(fileName, fields)//具体算法请参照源代码,或python算法

if err != nil {

ch

return

}

}

if flag.Funcs { //如果函数设置为真,导出函数和存储过程

err := exportFuncs(fileName, fields)//具体算法请参照源代码

if err != nil {

ch

return

}

}

//导出工作完成,向通道输入信息

ch

数据库查询通用封装,此工具只使用了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 mysql scan_golang 实现 mysql 数据库备份相关推荐

  1. mysql 表丢失_Mysql数据库备份 部分数据表丢失 Mysql table doesn't exist 解决

    问题: 直接拷贝data下的数据库数据进行备份,重装升级了数据库,直接复制备份数据到新的数据库data目录下,发现部分数据表不见了. 原因分析: 以表"Table"为例: 如类型是 ...

  2. MySQL命令之mysqldump -- 数据库备份程序

    文章目录 命令介绍 常用选项 参考示例 将指定数据表的数据导出为 SQL 脚本文件和文本文件 将指定的多个数据表的数据导出为 SQL 脚本文件和文本文件 将指定数据库导出到脚本文件中 将指定的多个数据 ...

  3. mysql备库命令_mysql数据库备份命令

    备份MySQL数据库的命令 mysqldump -hhostname -uusername -ppassword databasename > backupfile.sql 备份MySQL数据库 ...

  4. mysql 各种恢复_Mysql数据库备份和还原常用的命令

    1.备份MySQL数据库的命令 mysqldump-hhostname-uusername-ppassword databasename>backupfile.sql 2.备份MySQL数据库为 ...

  5. mysql如何用jsp代码进行数据库备份_mysql如何用jsp代码进行数据库备份

    mysql如何用jsp代码进行数据库备份 //导出 String mysql="mysqldump -uroot -proot --opt databasename > d:/test ...

  6. 同步云数据库MySQL到自建数据库

    摘要: 同步云数据库MySQL到自建数据库 备份恢复到本地的相关说明,请参考https://help.aliyun.com/knowledge_detail/41817.html 本例环境为 Mysq ...

  7. 数据库备份的两种方法

    数据库备份是必要的一般都是使用mysqldump进行备份,我这边写了两种备份方法可以参考一下. 第一种:使用mysqldump结合exec函数进行数据库备份操作. 代码如下: /*** Subject ...

  8. mysql数据库备份方案_MySQL平台数据库备份方案详细说明

    在数据库表丢失或损坏的情况下,备份你的数据库是很重要的.如果发生系统崩溃,你肯定想能够将你的表尽可能丢失最少的数据恢复到崩溃发生时的状态.有时,正是MySQL管理员造成破坏.管理员已经知道表已破坏,用 ...

  9. javaweb实现mysql备份功能_java web 实现mysql 数据库备份、恢复

    如题,由于项目需要,研究并实现了java web的 mysql数据库的备份.下载.恢复功能,中间遇到一些问题,耗费了不少时间,下面让我一一道来: 背景介绍: window 7系统 mysql 5.7 ...

最新文章

  1. 生物技术行业十年回顾:微生物组发展未达预期?
  2. 电脑有独显内存还被占用_独显和集成显卡怎么分别
  3. 一行Java代码实现不用区分系统获取Tomcat下的某路径
  4. 汇编语言LAHF和SAHF指令
  5. css 3d魔方源代码,CSS3 3D环境实现立体 魔方效果代码(示例代码)
  6. python构建知识库_使用Mediawiki构建个人知识库
  7. mongodb修改最大连接数
  8. Spring Boot Mybatis 搞反向工程,太方便咯。。
  9. php如何输出换行,PHP怎样才能让输出的内容自动换行
  10. linux tar 打包排除指定目录
  11. 3D游戏编程——游戏的本质
  12. 2021-04-17
  13. 《人工智能导论》自然演绎推理
  14. 数字孪生 软著登记表 模板
  15. 怎样让公司全员贡献结构化内容?
  16. 一个好用的vscode文件图标美化插件
  17. studio 热重载应用_热重载 (Hot reload)
  18. vue 路由history模式打包部署 The requested URL * was not found on this server. 的解决方法
  19. Java JDBC数据库简单使用,封装连接,关闭
  20. word文档标注参考文献以及标注参考文献出现的直线问题的解决

热门文章

  1. MVC中 数据底层联合JQUERY实现动态的安全的验证机制
  2. Know more about Enqueue Deadlock Detection
  3. 【Win10 应用开发】实现数据的增量加载
  4. ajax学习笔记之一
  5. 一个简单的调用动态库的实例
  6. 人物和背景分离的快速方法
  7. linux系统调用是通过软中断实现的吗
  8. centOS安装oracleDB,静默安装DBCA的时候,报错
  9. 64位双系统Ubuntu 14.04 LTS + Caffe + CUDA 7.5 + Opencv 3.0 安装配置实战
  10. 用户登录程序--绘制--遍历窗口