So implementieren Sie eine MySQL-Datenbanksicherung in Golang

So implementieren Sie eine MySQL-Datenbanksicherung in Golang

Hintergrund

Navicat ist das beste MySQL-Visualisierungstool. Beim Importieren und Exportieren von Ansichten verarbeitet es diese jedoch in alphabetischer Reihenfolge der Ansichtsnamen. Wenn Ansichten Abhängigkeiten aufweisen, werden während des Importvorgangs Fehler gemeldet. Ich habe zuvor eines in Python geschrieben, aber bei der Verwendung bin ich auf die Xfffd-Kodierung gestoßen und Pythons pymysql stürzte direkt ab. Ich habe festgestellt, dass Golang dieses Problem nicht hat, also habe ich es in Go neu geschrieben, um mich mit Golang vertraut zu machen.

Einige wichtige Punkte

  1. map & json, bei der Verarbeitung von Primärschlüssel- und Fremdschlüsselinformationen müssen Sie die JSON-Datenstruktur zum Speichern von Zwischenergebnissen verwenden. Da dies flexibel gehandhabt werden muss, kann es in Golang nur mit map[string]interface{} gehandhabt werden.
  2. interface{} entspricht einem Objekt in Java, das jeden Datentyp akzeptieren kann. Das ist praktisch, aber Sie müssen sich dessen bewusst sein, wenn Sie es verwenden, da das Programm sonst abstürzt, wenn der Datentyp nicht übereinstimmt.
  3. xfffd ist ein Platzhalter in utf8. Nachdem utf8mb4 außerhalb des Bereichs in der Datenbank gespeichert wurde, wird es als xfffd gespeichert. Beim Exportieren von Daten muss es herausgefiltert werden.
  4. goroutine, die Parallelitätsunterstützung von golang ist einzigartig. Unser Tool unterstützt die gleichzeitige Sicherung mehrerer Bibliotheken und es ist einfach, mit goroutine Parallelität zu erreichen.

Code-Analyse

Erklären Sie den Kerncode anhand des Funktionsmoduls

main.go, Parallelität, Befehlszeilenargumente

Verwenden Sie Befehlszeilenparameter, um einen Parameter zum Angeben des Sicherungsinhalts zu akzeptieren

Paket allgemein

Typ OpFlag-Struktur {
  Tables bool //Tabellenstruktur Datum bool //Tabellenstruktur und Daten Views bool //Ansicht Funcs bool //Funktionen und gespeicherte Prozeduren}

main.go, Programmeintrag, Verarbeitung von Kommandozeilenparametern

 wenn len(os.Args) > 1 {
    Flagge = allgemein.OpFlag{
      Tabellen: false,
      Datum: false,
      Ansichten: falsch,
      Funktionen: false,
    }
    switch os.Args[1] { //Akzeptiere einen Parameter case "table":
      flag.Tables = true //Setze den Bezeichner entsprechend dem Parameter case "data":
      flag.Tabellen = true
      flag.Datum = true
    Fall „Ansichten“:
      flag.Ansichten = true
    Fall "Funktionen":
      flag.Funcs = true
    Standard: //Falsche Parameter, Fehler melden und Protokoll beenden.Schwerwiegend("Ihr Argument muss in Tabelle, Daten, Ansichten oder Funktionen enthalten sein.")
    }
  }else{ //Keine Parameter, alle Flags werden standardmäßig exportiert = common.OpFlag{
      Tabellen: true,
      Datum: wahr,
      Ansichten: wahr,
      Funktionen: true,
    }
  }
  err := backUp.Export(flag) Sichern Sie die Datenbank entsprechend den Parametern

Exportieren.go

Sichern Sie den Hauptprozess, generieren Sie eine Goroutine gemäß configs.json, um die Datenbank zu sichern, und warten Sie, bis der Vorgang abgeschlossen ist.

var Konfigurationsschnittstelle{}
  fr, err := os.Open("./configs.json")
  wenn err != nil {
    Rückgabefehler
  }
  decoder := json.NewDecoder(fr) //Konfigurationsdatei analysieren err = decoder.Decode(&configs)
  confs := Konfigurationen.(map[string]Schnittstelle{})
  workDir := confs["workDir"].(Zeichenfolge)
  ch := make(chan string) //Kanalvariable für Schlüssel, Wert := Bereich confs {
    wenn strings.HasPrefix(Schlüssel, "db_") {
      dbConf := Wert.(map[string]interface{})
      dbConn := common.DbConnFields{ //Datenbankkonfiguration DbHost: dbConf["db_host"].(string),
        DbPort: int(dbConf["db_port"].(float64)),
        DbUser: dbConf["db_user"].(Zeichenfolge),
        DbPass: dbConf["db_pass"].(Zeichenfolge),
        DbName: dbConf["db_name"].(Zeichenfolge),
        DbCharset: dbConf["db_charset"].(Zeichenfolge),
      }
      if dbConf["file_alias"] != nil { //Generiere den Namen der SQL-Sicherungsdatei dbConn.FileAlias ​​​​= dbConf["file_alias"].(string)
      }
      go ExportOne(dbConn, workDir, ch, flag) //Coroutine erstellen}
  }
  for key := range confs { //Blockiere den Hauptprozess und warte bis alle Coroutinen ihre Arbeit beendet haben if strings.HasPrefix(key, "db_") {
      fmt.Print( <- ch )
    }
  }
  Rückgabe Null

Sie müssen die folgende Konfigurationsdatei schreiben, um die Datenbank zu beschreiben, die Sie sichern möchten:

{
  "Datenbankname1": {
    "db_host": "192.168.1.8",
    "db_port": 3306,
    "db_user": "root",
    "db_pass": "123456",
    "db_name": "name1",
    "db_charset": "utf8mb4",
    "file_alias": "Dateiname1"
  },
  "Datenbankname2": {
    "db_host": "lokaler Host",
    "db_port": 3306,
    "db_user": "root",
    "db_pass": "123456",
    "Datenbankname": "Name2",
    "db_charset": "utf8mb4"
  },
  "Datenbankdialekt": "mysql",
  "Arbeitsverzeichnis": "/home/zhoutk/gocodes/goTools/"
}

ExportOne.go

Sichern einer Datenbank

Dateiname := Felder.Dateialias
  setSqlHeader(fields, fileName) //Beschreibung der Exportdatei festlegen if flag.Tables { //Wenn die Tabelle auf true gesetzt ist, Tabellenstruktur exportieren err := exportTables(fileName, fields, flag) //Spezifische Algorithmen finden Sie im Quellcode if err != nil {
      ch <- fmt.Sprintln("Fehler: ", fields.DbName, "\t export tables throw, \t", err)
      zurückkehren
    }
  }
  if flag.Views { //Wenn die Ansicht auf „true“ gesetzt ist, exportiere die Ansicht err := exportViews(fileName, fields) //Den spezifischen Algorithmus findest du im Quellcode oder im Python-Algorithmus if err != nil {
      ch <- fmt.Sprintln("Fehler: ", fields.DbName, "\t export views throw, \t", err)
      zurückkehren
    }
  }
  if flag.Funcs { //Wenn die Funktion auf true gesetzt ist, werden Funktionen und gespeicherte Prozeduren exportiert err := exportFuncs(fileName, fields) //Spezifische Algorithmen finden Sie im Quellcode if err != nil {
      ch <- fmt.Sprintln("Fehler: ", fields.DbName, "\t export funcs throw, \t", err)
      zurückkehren
    }
  }
  //Export abgeschlossen, Eingabeinformationen zum Kanal ch <- fmt.Sprintln("Export ", fields.DbName, "\t Erfolg bei \t", time.Now().Format("2006-01-02 15:04:05"))

MysqlDao.go

Allgemeine Kapselung von Datenbankabfragen, dieses Tool verwendet nur ExecuteWithDbConn. Verwenden Sie map und interface{} flexibel, um die Ergebnisse in Schlüssel-Wert-Objekte umzuwandeln und zurückzugeben.

func ExecuteWithDbConn(sql string, Werte []Schnittstelle{}, Felder common.DbConnFields) (map[string]Schnittstelle{}, Fehler) {
  rs := make(map[string]schnittstelle{})
  dao, err := mysql.Open("mysql", Felder.DbUser + ":"+Felder.DbPass+"@tcp("+Felder.DbHost+":"+
    strconv.Itoa(Felder.DbPort)+")/"+Felder.DbName+"?charset="+Felder.DbCharset)
  verschieben dao.Close()
  wenn err != nil {
    rs["Code"] = 204
    returniere rs, err
  }
  stmt, err := dao.Vorbereiten(sql)
  wenn err != nil {
    rs["Code"] = 204
    returniere rs, err
  }
  Zeilen, Fehler := stmt.Query(Werte…)
  wenn err != nil {
    rs["Code"] = 204
    returniere rs, err
  }
  columns, err := rows.Columns() //Feldnamen abrufen vs := make([]mysql.RawBytes, len(columns))
  scannt := make([]interface{}, len(columns))
  für i := Bereich vs { //voreingestellter Wert Adresse scans[i] = &vs[i]
  }
  var Ergebnis []map[string]interface{}
  für Zeilen.Weiter() {
    _ = rows.Scan(scans...) //Geben Sie jeweils eine Spalte mit Werten ein := make(map[string]interface{})
    für i, col := Bereich vs {
      wenn col != nil {
        each[columns[i]] = FilterHolder(string(col)) //Filter/xfffd
      }anders{
        jede[Spalten[i]] = nil
      }
    }
    Ergebnis = Anhängen(Ergebnis, jedes)
  }
  rs["Code"] = 200
  //Daten, _ := json.Marshal(Ergebnis)
  rs["Zeilen"] = Ergebnis
  returniere rs, err
}

Projektgalerie

https://github.com/zhoutk/goTools

Anwendung

Git-Klon https://github.com/zhoutk/goTools
cd goTools
hol
Führen Sie main.go aus.
Erstellen Sie main.go
./main #alles aus der Datenbank exportieren
./Haupttabelle #Tabellen exportieren
./Hauptdaten #Tabellen und Daten exportieren
./Hauptansichten #Ansichten exportieren
./main funcs #Funktionen und gespeicherte Prozeduren exportieren

Zusammenfassen

Oben ist die vom Herausgeber vorgestellte Vorgehensweise zum Sichern einer MySQL-Datenbank mit Golang beschrieben. Ich hoffe, sie ist für alle hilfreich. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Herausgeber wird Ihnen rechtzeitig antworten. Ich möchte auch allen für ihre Unterstützung der Website 123WORDPRESS.COM danken!

Das könnte Sie auch interessieren:
  • Golang stellt über einen SSH-Proxy eine Verbindung zu MySQL her
  • Herstellen einer Verbindung zur MySQL-Datenbank in Golang
  • Führen Sie die Schritte von Golang aus, um eine MySql-Datenbank zu betreiben
  • So betreiben Sie MySQL in Golang
  • Implementierungscode zum Betreiben einer MySQL-Datenbank in Golang
  • Der Golang-Vorgang stellt eine Verbindung zur Datenbank her, um ein MySQL-Transaktionsbeispiel zu implementieren

<<:  Konventionelle JS-Verarbeitungsfunktionen für die Entwicklung von Vue Element-Frontend-Anwendungen

>>:  Linux löst das Problem, dass Deepin den Google Chrome-Browser nicht als Root-Benutzer starten kann

Artikel    

Artikel empfehlen

Schritte zum Bereitstellen eines Spring Boot-Projekts mit Docker

Inhaltsverzeichnis Erstellen Sie ein einfaches Sp...

So richten Sie den Ziellink eines Tags auf ein Iframe

Code kopieren Der Code lautet wie folgt: <ifra...

Reflexion und Proxy in Front-End-JavaScript

Inhaltsverzeichnis 1. Was ist Reflexion? 2. Refle...

Hinweise zur Verwendung des Blockquote-Tags

<br />Semantisierung lässt sich nicht mit we...

Detaillierte Erklärung der Beziehung zwischen React und Redux

Inhaltsverzeichnis 1. Die Beziehung zwischen Redu...

Lösung zum Einfügen eines Formulars mit einer Leerzeile oben und unten

Ich weiß nicht, ob Ihnen beim Erstellen einer Webs...

So überspringen Sie Fehler bei der MySQL-Master-Slave-Replikation

1. Traditionelle Binlog-Master-Slave-Replikation,...

Implementierung der kontinuierlichen Integration von Jenkins+Docker

Inhaltsverzeichnis 1. Einführung in Jenkins 2. Je...

Erste Schritte mit MySQL - Konzepte

1. Was ist das? MySQL ist das beliebteste relatio...

So zeigen Sie im Hintergrund laufende Programme in Linux an und schließen sie

1. Führen Sie die .sh-Datei aus Sie können es dir...

MySQL-Techniken zum schnellen Datenvergleich

Im MySQL-Betrieb und bei der Wartung möchte ein F...