GolangでMySQLデータベースのバックアップを実装する方法

GolangでMySQLデータベースのバックアップを実装する方法

背景

Navicat は、最高の MySQL 視覚化ツールです。ただし、ビューのインポートとエクスポートに関しては、ビュー名のアルファベット順に処理されます。ビューに依存関係がある場合は、インポート プロセス中にエラーが報告されます。以前 Python で書いたことがありますが、それを使用すると xfffd エンコーディングが発生し、Python の pymysql が直接クラッシュしてしまいました。 golang にはこの問題がないことがわかったので、golang に慣れるために go で書き直しました。

いくつかの重要なポイント

  1. map & jsonでは、主キーと外部キーの情報を処理する際に、中間結果を格納するためにjsonデータ構造を使用する必要があります。柔軟に対応する必要があるため、golangではmap[string]interface{}でしか扱うことができません。
  2. interface{} は Java のオブジェクトに相当し、任意のデータ型を受け入れることができます。これは便利ですが、使用時には注意が必要です。そうしないと、データ型が一致しない場合にプログラムがクラッシュします。
  3. xfffd は utf8 のプレースホルダーです。範囲外の utf8mb4 がデータベースに保存されると、xfffd として保存されます。データをエクスポートするときには、これを除外する必要があります。
  4. goroutine は、golang の並行処理サポートがユニークです。当社のツールは、複数のライブラリの同時バックアップをサポートしており、goroutine を使用して簡単に並列処理を実現できます。

コード分​​析

機能モジュールごとにコアコードを説明する

main.go、並行性、コマンドライン引数

コマンドラインパラメータを使用して、バックアップコンテンツを指定するパラメータを受け入れます。

パッケージ共通

OpFlag構造体型{
  Tables bool //テーブル構造 Datum bool //テーブル構造とデータ Views bool //ビュー Funcs bool //関数とストアドプロシージャ}

main.go、プログラムエントリ、コマンドラインパラメータの処理

 len(os.Args) > 1 の場合 {
    フラグ = common.OpFlag{
      表: 偽、
      データ: 偽、
      閲覧数: false、
      関数: false、
    }
    switch os.Args[1] { //パラメータを受け入れる case "table":
      flag.Tables = true //パラメータケース「data」に応じて識別子を設定します。
      flag.Tables = true
      flag.Datum = true
    ケース「ビュー」:
      flag.Views = true
    ケース "関数":
      flag.Funcs = true
    デフォルト: // パラメータが正しくありません。エラーを報告してログを終了します。致命的("引数はテーブル、データ、ビュー、または関数内になければなりません。")
    }
  }else{ //パラメータなし、すべてのフラグはデフォルトでエクスポートされます = common.OpFlag{
      表: 真、
      データ: true、
      閲覧数: true、
      関数: true、
    }
  }
  err := backUp.Export(flag) パラメータに従ってデータベースをバックアップします

エクスポート.go

メインプロセスをバックアップし、configs.json に従って goroutine を生成してデータベースをバックアップし、完了を待ちます。

var configs インターフェース{}
  fr, err := os.Open("./configs.json")
  err != nil の場合 {
    エラーを返す
  }
  デコーダー:= json.NewDecoder(fr) // 設定ファイルを解析します err = デコーダー.Decode(&configs)
  confs := configs.(map[文字列]インターフェース{})
  workDir := confs["workDir"].(文字列)
  ch := make(chan string) //キーのチャネル変数、値 := range confs {
    strings.HasPrefix(キー、"db_") の場合 {
      dbConf := 値.(map[文字列]インターフェース{})
      dbConn := common.DbConnFields{ //データベース構成 DbHost: dbConf["db_host"].(文字列),
        DbPort: int(dbConf["db_port"].(float64))、
        DbUser: dbConf["db_user"].(文字列)、
        DbPass: dbConf["db_pass"].(文字列)、
        DbName: dbConf["db_name"].(文字列)、
        DbCharset: dbConf["db_charset"].(文字列)、
      }
      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) 関数は、
    }
  }
  nilを返す

バックアップするデータベースを記述するには、次の構成ファイルを作成する必要があります。

{
  "db_name1": {
    "db_host": "192.168.1.8",
    「db_port」: 3306,
    "db_user": "ルート",
    "db_pass": "123456",
    "db_name": "name1",
    "db_charset": "utf8mb4",
    "file_alias": "ファイル名1"
  },
  "db_name2": {
    "db_host": "ローカルホスト",
    「db_port」: 3306,
    "db_user": "ルート",
    "db_pass": "123456",
    "db_name": "name2",
    "db_charset": "utf8mb4"
  },
  "データベース方言": "mysql",
  "作業ディレクトリ": "/home/zhoutk/gocodes/goTools/"
}

エクスポートワン

データベースのバックアップ

ファイル名:= フィールド.FileAlias
  setSqlHeader(fields, fileName) //エクスポートファイルの説明を設定します if flag.Tables { //テーブルがtrueに設定されている場合、テーブル構造をエクスポートします err := exportTables(fileName, fields, flag) //特定のアルゴリズムについては、ソースコードを参照してください if err != nil {
      ch <- fmt.Sprintln("エラー: ", fields.DbName, "\t エクスポート テーブルがスローされました, \t", err)
      戻る
    }
  }
  if flag.Views { //ビューがtrueに設定されている場合、ビューをエクスポートします err := exportViews(fileName, fields) //具体的なアルゴリズムについては、ソースコードまたはPythonアルゴリズムを参照してください if err != nil {
      ch <- fmt.Sprintln("エラー: ", fields.DbName, "\t エクスポート ビューがスローされました, \t", err)
      戻る
    }
  }
  if flag.Funcs { //関数がtrueに設定されている場合、関数とストアドプロシージャをエクスポートします err := exportFuncs(fileName, fields) //具体的なアルゴリズムについては、ソースコードを参照してください if err != nil {
      ch <- fmt.Sprintln("エラー: ", fields.DbName, "\t export funcs throw, \t", err)
      戻る
    }
  }
  //エクスポートが完了しました。チャネルに情報を入力します。 ch <- fmt.Sprintln("エクスポート ", fields.DbName, "\t 成功 \t", time.Now().Format("2006-01-02 15:04:05"))

翻訳元

データベース クエリの一般的なカプセル化。このツールは ExecuteWithDbConn のみを使用します。 map と interface{} を柔軟に使用して、結果をキー値オブジェクトに変換して返します。

func ExecuteWithDbConn(sql 文字列、値 [] インターフェース {}、フィールド common.DbConnFields) (map [文字列] インターフェース {}、エラー) {
  rs := make(map[文字列]インターフェース{})
  dao、err := mysql.Open("mysql", fields.DbUser + ":"+fields.DbPass+"@tcp("+fields.DbHost+":"+
    strconv.Itoa(fields.DbPort)+")/"+fields.DbName+"?charset="+fields.DbCharset)
  dao.Close() を延期する
  err != nil の場合 {
    rs["コード"] = 204
    rsを返す、エラー
  }
  stmt、err := dao.Prepare(sql)
  err != nil の場合 {
    rs["コード"] = 204
    rsを返す、エラー
  }
  行、エラー:= stmt.Query(値...)
  err != nil の場合 {
    rs["コード"] = 204
    rsを返す、エラー
  }
  columns, err := rows.Columns() //フィールド名を取得します vs := make([]mysql.RawBytes, len(columns))
  スキャン:= make([]interface{}, len(列))
  for i := range vs { // プリセット値アドレス scans[i] = &vs[i]
  }
  var result []map[文字列]インターフェース{}
  行のNext() {
    _ = rows.Scan(scans...) //値の列を入力します each := make(map[string]interface{})
    i, col := 範囲 vs {
      列がnilの場合{
        each[columns[i]] = FilterHolder(string(col)) //Filter/xfffd
      }それ以外{
        各[列[i]] = nil
      }
    }
    結果 = append(結果、それぞれ)
  }
  rs["コード"] = 200
  //データ、_ := json.Marshal(結果)
  rs["行"] = 結果
  rsを返す、エラー
}

プロジェクトギャラリー

https://github.com/zhoutk/goTools

使い方

git クローン https://github.com/zhoutk/goTools
cd goツール
取りに行く
main.go を実行します
ビルド main.go
./main #データベースのすべてをエクスポート
./main テーブル #テーブルをエクスポート
./main data #テーブルとデータをエクスポート
./メインビュー #エクスポートビュー
./main funcs #export 関数とストアド プロシージャ

要約する

上記は、編集者が紹介したgolangを使用してmysqlデータベースをバックアップする操作方法です。皆様のお役に立てれば幸いです。ご質問がある場合は、メッセージを残してください。編集者がすぐに返信します。また、123WORDPRESS.COM ウェブサイトをサポートしてくださっている皆様にも感謝申し上げます。

以下もご興味があるかもしれません:
  • GolangはSSHプロキシ経由でMySQLに接続する
  • Golang で MySQL データベースに接続する
  • GolangでMySqlデータベースを操作するための完全な手順
  • GolangでMySQLを操作する方法
  • GolangでMySQLデータベースを操作するための実装コード
  • Golang 操作はデータベースに接続して、mysql トランザクションの例を実装します。

<<:  Vue Element フロントエンドアプリケーション開発のための従来の JS 処理機能

>>:  Linux は、Deepin がルートユーザーとして Google Chrome ブラウザを起動できない問題を解決します

推薦する

サーバー間のファイル バックアップ ソリューション、サーバー ファイルを別のサーバーに自動的にバックアップする方法は?

多くの組織ではファイル サーバーをバックアップする必要があり、あるサーバーから別のファイル サーバー...

Dockerイメージを構築する2つの方法

目次既存のイメージからイメージを更新します。イメージを最初から構築する: Docker イメージ リ...

Linux カーネル デバイス ドライバーのメモリ管理に関する注意事項

/************************ * Linux メモリ管理 *********...

jQueryのコア機能とイベント処理の詳細な説明

目次イベントページの読み込みイベント委任イベントの切り替えイベント要約するイベントページの読み込み1...

Javascript Bootstrapのグリッドシステム、ナビゲーションバー、カルーセルの詳細な説明

目次ブートストラップと関連コンテンツの紹介グリッドシステムネストされた列列オフセット列の並べ替えナビ...

露滴アニメーション効果を実装するための Three.js サンプル コード

序文みなさんこんにちは。CSS ウィザードの alphardex です。この記事では、three.j...

LDAP ユーザー認証を使用するように Linux を構成する方法

私は CentOS に実装された LDAP ユーザー管理を使用しています。これはインターネット上のほ...

Dockerコンテナにホストディレクトリへの書き込み権限がない場合の解決策

Docker コンテナを適用する場合、多くの場合、ホスト ディレクトリを Docker コンテナにマ...

訪問者を惹きつけるウェブサイトコンテンツを作成する14の方法

ネットサーフィンをしていると、私の注意を引こうとする美しいグラフィックでいっぱいの Web サイトを...

JavaScriptはブラウザがIEかどうかを判定します

フロントエンド開発者としては、IEの落とし穴は避けて通れません。他のブラウザはいいのにIEは壊れてい...

スライド効果を実現するためのネイティブJavaScript

ページ、特にホームページを作成するときは、通常、Web サイト全体の他のメイン ページにリンクできる...

MySQL 5.7.16 ZIP パッケージのインストールと設定のチュートリアル

この記事では、MySQL 5.7.16 ZIPパッケージのインストールと設定のチュートリアルを参考ま...

マウスを傾けた状態でのフリップナビゲーションの問題に関する研究

この記事では、マウス フリップナビゲーションの制作についてまだ疑問を持っている友人の役に立つことを期...

CSSはコンテンツの高さが足りない場合にフッターを自動的に下部に固定します

UI カットのプロセスでは、ページはヘッダー、コンテンツ、フッターの 3 つの部分で構成されることが...

Mysql の一時テーブルとパーティションテーブルの違いの詳細な説明

一時テーブルとメモリテーブルメモリ テーブルとは、メモリ エンジンを使用するテーブルを指します。テー...