9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【GitHub Actions】download-artifact した csv ファイルをそのまま MySQL に高速インポートする

Posted at

解決したい課題

  • GitHub-Hosted Runner上のJob内で生成したcsvファイルを、Self-Hosted Runnerのジョブに渡して社内ネットワーク内のMySQLサーバーに接続したい
  • csvデータ中身を読み込んでINSERTのSQLクエリを実行する処理を簡潔にしたい

解決する方法

MySQLには高速でテキストファイルを読み込んでテーブルに突っ込む LOAD DATA STATEMENT があるので、ワークフロー内でこれを使う。

YAML(GitHub Actionsのワークフローファイル)

CSVの生成は GitHub-Hosted Runner 上で、csvファイルのINSERTは Self-Hosted Runner 上でやりたいのでジョブを分けています。

refresh-mysql-db.yml
name: reflesh-mysql-data
on:
  workflow_dispatch:

jobs:
  create-and-upload-csv:
    runs-on: ubuntu-latest
    steps:  
      - uses: actions/checkout@v4
      - name: Create CSV file
        run: |
          echo "id,name,age" > example.csv
          echo "1,Tomitarou,67" >> example.csv
      - name: Upload CSV as artifact
        uses: actions/upload-artifact@v4
        with:
          name: example-csv
          path: example.csv

  refresh-mysql-data:
    needs: create-and-upload-csv
    runs-on: [self-hosted, linux, x64]
    container: 
      # 今回は AWS ECR Public Gallery にある Docker の公式 MySQL イメージを使用
      # Pull Through Cache 機能を介してキャッシュされるようにしている
      image: xxxxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-public/docker/library/mysql:latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4 # 前のジョブで作ったcsvをダウンロード
        with:
          name: example-csv
          path: downloaded
      - name: Refresh MySQL Data
        env:
          # あらかじめリポジトリの Secrets and variables に設定しておく
          MYSQL_HOST: ${{ vars.MYSQL_HOST }}
          MYSQL_USER: ${{ secrets.MYSQL_USER }}
          MYSQL_PASSWORD: ${{ secrets.MYSQL_PASSWORD }}
          MYSQL_DB_NAME: ${{ vars.MYSQL_DB_NAME }}
        run: mysql --host=${MYSQL_HOST} --user=${MYSQL_USER} --password=${MYSQL_PASSWORD} ${MYSQL_DB_NAME} --local-infile=1 -e "$(cat path/to/refresh_data.sql)"

SQLファイル

  • ファイルPATH:path/to/refresh_data.sql
  • サンプルとして、テーブルに対してDELETE-INSERT のクエリを投げるようにしている
  • 対象のテーブル増やしたければ、csbとテーブルの指定を変えてSQLファイル内に追加するだけ
refresh_data.sql
START TRANSACTION;
DELETE FROM HOGE_TABLE;
LOAD DATA LOCAL INFILE "downloaded/example.csv" INTO TABLE HOGE_TABLE FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' IGNORE 1 LINES;
COMMIT;

ちょっとだけ補足

  • YAML:
    • MySQLクライアント起動時に指定する --local-infile=1 オプション
      • MySQLサーバーにローカルファイル(クライアント側で生成されたファイル)を読み込むことを許可する設定
      • この設定値が 0 だと利用できないので注意(逆にセキュリティやデータの整合性を維持するために設定値を 0 にしておいた方がよい場合もあるので要確認)
  • SQL(LOAD DATA Statement):
    • LOCAL
      • クライアントマシンにあるファイルを読み込むよう指定
    • INFILE 'downloaded/example.csv'
      • MySQLにロードするデータファイルへのパスを指定
    • INTO TABLE HOGE_TABLE
      • データをロードする対象のテーブルを指定
    • FIELDS TERMINATED BY ','
      • 各フィールド(列)をどの文字で区切るかを明示的に指定
      • 今回はCSVなのでカンマ(,)を区切り文字として使う
    • OPTIONALLY ENCLOSED BY '"'
      • フィールドの値が必要に応じて引用符(")で囲まれていることを指定
      • フィールド値の中にカンマが含まれている場合の対策)
    • IGNORE 1 LINES
      • CSVファイルの最初のヘッダー行を無視するために指定

注意点

  • MySQLのトランザクションについて
    • AUTOCOMMIT オプション:MySQL はデフォルトで ON になっている
    • LOAD DATA StatementNDB strage engine 使用時のみ暗黙的commitになる(トランザクション制御が不可能)

The statements listed in this section (and any synonyms for them) implicitly end any transaction active in the current session, as if you had done a COMMIT before executing the statement.(訳:以下に書かれているstatementは暗黙的に現在のトランザクションを終了しちゃうよ)

  • ...
  • Data loading statements. LOAD DATA. LOAD DATA causes an implicit commit only for tables using the NDB storage engine.
  • ...

なので、トランザクション制御できるかどうか、ストレージエンジンを1度見たほうがよさげ。

strage engine の調査クエリ
SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'データベース名';
結果のサンプル
┌──────────────┬────────────┐
│  TABLE_NAME  │   ENGINE   │
├──────────────┼────────────┤
│ HOGE_TABLE   │   InnoDB   │ ← InnoDBはトランザクション制御できそう
│ FUGA_TABLE   │   InnoDB   │
│ PIYO_TABLE   │   InnoDB   │
└──────────────┴────────────┘

参考

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?