background Navicat is the best MySQL visualization tool. However, when it comes to importing and exporting views, it processes them in alphabetical order of view names. If views have dependencies, errors will be reported during the import process. I have written one in Python before, but when using it, I encountered xfffd encoding and Python's pymysql would crash directly. I found that golang does not have this problem, so I rewrote it in go to get familiar with golang. Some key points
Code Analysis Explain the core code by functional module main.go, concurrency, command line arguments Use command line parameters to accept a parameter to specify the backup content package common type OpFlag struct { Tables bool //Table structure Datum bool //Table structure and data Views bool //View Funcs bool //Functions and stored procedures} main.go, program entry, processing command line parameters if len(os.Args) > 1 { flag = common.OpFlag{ Tables: false, Datum: false, Views: false, Funcs: false, } switch os.Args[1] { //Accept a parameter case "table": flag.Tables = true //Set the identifier according to the parameter case "data": flag.Tables = true flag.Datum = true case "views": flag.Views = true case "funcs": flag.Funcs = true default: //Incorrect parameters, report error and exit log.Fatal("You arg must be in: table, data, views or funcs.") } }else{ //No parameters, all flags are exported by default = common.OpFlag{ Tables: true, Datum: true, Views: true, Funcs: true, } } err := backUp.Export(flag) Back up the database according to the parameters Export.go Back up the main process, generate goroutine according to configs.json to back up the database, and wait for completion. var configs interface{} fr, err := os.Open("./configs.json") if err != nil { return err } decoder := json.NewDecoder(fr) //Parse the configuration file err = decoder.Decode(&configs) confs := configs.(map[string]interface{}) workDir := confs["workDir"].(string) ch := make(chan string) //channel variable for key, value := range confs { if strings.HasPrefix(key, "db_") { dbConf := value.(map[string]interface{}) dbConn := common.DbConnFields{ //Database configuration 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 { //Generate the name of the sql backup file dbConn.FileAlias = dbConf["file_alias"].(string) } go ExportOne(dbConn, workDir, ch, flag) //Create coroutine} } for key := range confs { //Block the main process and wait for all coroutines to complete their work if strings.HasPrefix(key, "db_") { fmt.Print( <- ch ) } } return nil You need to write the following configuration file to describe the database you want to back up: { "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 Backing up a database fileName := fields.FileAlias setSqlHeader(fields, fileName) //Set the export file description if flag.Tables { //If the table is set to true, export the table structure err := exportTables(fileName, fields, flag) //For specific algorithms, please refer to the source code if err != nil { ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export tables throw, \t", err) return } } if flag.Views { //If the view is set to true, export the view err := exportViews(fileName, fields) //For the specific algorithm, please refer to the source code or Python algorithm if err != nil { ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export views throw, \t", err) return } } if flag.Funcs { //If the function is set to true, export functions and stored procedures err := exportFuncs(fileName, fields) //For specific algorithms, please refer to the source code if err != nil { ch <- fmt.Sprintln("Error: ", fields.DbName, "\t export funcs throw, \t", err) return } } //Export completed, input information to the channel ch <- fmt.Sprintln("Export ", fields.DbName, "\t success at \t", time.Now().Format("2006-01-02 15:04:05")) MysqlDao.go Database query general encapsulation, this tool only uses ExecuteWithDbConn. Use map and interface{} flexibly to convert the results into key-value objects and return them. 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() //Get the field name vs := make([]mysql.RawBytes, len(columns)) scans := make([]interface{}, len(columns)) for i := range vs { //preset value address scans[i] = &vs[i] } var result []map[string]interface{} for rows.Next() { _ = rows.Scan(scans...) //Enter a column of values each := make(map[string]interface{}) for i, col := range vs { if col != nil { each[columns[i]] = FilterHolder(string(col)) //Filter/xfffd }else{ each[columns[i]] = nil } } result = append(result, each) } rs["code"] = 200 //data, _ := json.Marshal(result) rs["rows"] = result return rs, err } Project gallery https://github.com/zhoutk/goTools How to use git clone https://github.com/zhoutk/goTools cd goTools go get go run main.go go build 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 Summarize The above is the operation method of using golang to backup mysql database introduced by the editor. I hope it will be helpful to everyone. If you have any questions, please leave me a message and the editor will reply to you in time. I would also like to thank everyone for their support of the 123WORDPRESS.COM website! You may also be interested in:
|
<<: Linux solves the problem that Deepin cannot start Google Chrome browser as root user
>>: WeChat applet realizes simple tab switching effect
The search performance from fastest to slowest is...
Join query A join query refers to a matching quer...
Preface In the previous article Detailed Explanat...
Table of contents 2. Stack analysis using pt-pmap...
I have been engaged in Java web development for mo...
The datetime type is usually used to store time i...
Table of contents 1. How to monitor Tomcat 2. Jav...
I installed a new version of MySQL (8.0.21) today...
The specific code is as follows: <!DOCTYPE htm...
Async Hooks is a new feature of Node8. It provide...
1. Download the installation package from the off...
Regarding display: flex layout, some people have ...
Preface This article mainly introduces a problem ...
This article mainly introduces the process of imp...
For record, it may be used in the future, and fri...