20210426のMySQLに関する記事は2件です。

Go RestAPI のあれこれ ついでにDockerも

今回できたこと Goを使用してREST APIを作成した。 その際,Dockerを使用し,フレームワークには軽量なechoを使用した。 また,SSL化も行い,Let`s Encriptを使用した。 最初に知っておきたいコマンド (全削除) (コンテナ)$ docker rm -f `docker ps -a -q` (イメージ)$ docker rmi $(docker images -q) -f (build) $ docker-compose up -d --build (コンテナ起動) $ docker-compose exec golang bash (動いているdocker一覧表示) $ docker-compose ps (作成した全てのdocker一覧表示) $ docker-compose ps -a (コンテナ内に入る) $ docker-compose exec golang bash $ docker-compose exec mysql bash (MySQL接続) root@コンテナ番号:/# mysql -u root -p -h 127.0.0.1 mysql> show databases; mysql> use golang; mysql> show tables; mysql> SELECT * FROM `users`; 全容 初期設定 docker, docker-compose インストール済み Docker のインストール手順 Docker Compose のインストール フォルダは以下を作る └─プロジェクト名 ├─server │ ├─docker │ │ ├─golang │ │ │ └─Dockerfile │ │ ├─mysql │ │ │ ├─Dockerfile │ │ │ └─db │ │ │ └─init.sql │ │ ├─src │ │ │ ├─crt <-Dockerで自動生成(証明書が入る予定) │ │ │ ├─databases │ │ │ │ └─main.go │ │ │ ├─routing │ │ │ │ └─main.go │ │ │ ├─go.mod <-自動生成 │ │ │ ├─go.sum <-自動生成 │ │ │ └─main.go │ │ ├─docker-compose.yml │ │ └─api_v1.yaml <-必要に応じて │ └─Server.md <-必要に応じて └─README.md <-必要に応じて 証明書作成 無料の認証局を利用する Let`s Encrypt certbot 証明書が生成されているか確認する $ ls /etc/letsencrypt/live/<自分のドメイン名> >> README cert.pem chain.pem fullchain.pem privkey.pem プロジェクトを書き込み DockerComposeの設定 docker-compose.yml version: "3" services: golang: build: ./golang/ image: image_golang container_name: container_api volumes: - ./src:/go/src # 証明書を/go/src/crtへ - /etc/letsencrypt:/go/src/crt ports: - "443:443" tty: true mysql: # platform: linux/x86_64 #AppleSiliconを使用時,必要 build: ./mysql/ image: image_mysql container_name: container_db volumes: - ./mysql/db:/docker-entrypoint-initdb.d #初期データをマウントする場所 environment: # コンテナ内のMySQLを起動する際のパスワードを設定 - MYSQL_DATABASE=golang # 作成するデータベース名 - MYSQL_USER=akidon # 作業ユーザー名(任意の値) - MYSQL_PASSWORD=12345 # 作業ユーザーのパスワード(任意の値) - MYSQL_ROOT_PASSWORD=root # rootユーザーのパスワード(デフォルトでは「root」) ports: - "3306:3306" tty: true 説明 versionは3系が最新版で、versionによって書き方が異なる build: Dockerfileが存在する場所 image: イメージの名前 container_name: コンテナの名前 volumes: 「./a:/b」 aはホスト側のフォルダを bのdockerコンテナ側へ ports: ポート environment: 環境変数 tty: true コンテナ起動永続化 links: 他のコンテナの接続? AppleSiliconを使用している場合は17行目のリマークを外す DockerFileの設定 golang/Dockerfile. # golang/Dockerfile FROM golang:1.14 WORKDIR /go/src mysql/Dockerfile. # mysql/Dockerfile FROM mysql MySQLの初期設定 init.sql -- MySQL dump 10.13 Distrib 5.1.51, for pc-linux-gnu (i686) -- -- Host: 127.0.0.1 Database: world -- ------------------------------------------------------ -- Server version 5.1.51-debug-log /*以下Databaseの内容が記載される*/ DROP SCHEMA IF EXISTS golang; CREATE SCHEMA golang; USE golang; DROP TABLE IF EXISTS golang; CREATE TABLE users ( id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, name VARCHAR(40), age INT(10), created_at TIMESTAMP DEFAULT NULL, updated_at TIMESTAMP DEFAULT NULL, deleted_at TIMESTAMP DEFAULT NULL ); INSERT INTO users (id, name, age) VALUES (1, "testKun", 21); 説明 created_at updated_at deleted_at はGormを使用する際,追加,更新,削除で必要になる要素 Goの設定 databases/main.go package databases import ( "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) // SQLConnect DB接続 func GormConnect() (database *gorm.DB) { DBMS := "mysql" // MySQL PROTOCOL := "tcp(container_db)" // MySQLコンテナ名 DBNAME := "golang" // テーブル名 USER := "akidon" // MySQLユーザー名 PASS := "12345" // パスワード CONNECT := USER + ":" + PASS + "@" +PROTOCOL + "/" + DBNAME + "?charset=utf8&parseTime=True&loc=Local" // 修正!! db, err := gorm.Open(DBMS, CONNECT) if err != nil { panic(err.Error()) } else { fmt.Println("DB接続成功") } return db } 説明 PROTOCOL := "tcp(container_db)" // MySQLコンテナ名 のcontainer_dbはDockerComposeのcontainer_name:によるもの 間違っていれば接続できない routing/main.go package routing import ( "fmt" "github.com/labstack/echo" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" "src/databases" ) type User struct { gorm.Model Name string `json:"name"` Age int `json:"age"` } func (u User) String() string { return fmt.Sprintf("Name:%s \n Age:%d \n ", u.Name, u.Age) } // ユーザー情報取得 func BaseAPI_GET() echo.HandlerFunc { return func(c echo.Context) error { db := databases.GormConnect() defer db.Close() text1 := search(db) return c.JSON(200, text1) } } // ユーザーを登録,更新 func BaseAPI_POST() echo.HandlerFunc { return func(c echo.Context) error { db := databases.GormConnect() defer db.Close() //追加・更新 user := new(User) if err := c.Bind(user); err != nil { return err } user1 := User{ Name: user.Name, Age: user.Age, } insertUsers := []User{user1} insert(insertUsers, db) // update(user1, db) return c.JSON(200, "追加完了") } } func insert(users []User, db *gorm.DB) { for _, user := range users { db.NewRecord(user) db.Create(&user) } } func update(users User, db *gorm.DB) { var user User db.Model(&user).Where("id = ?", 1).Update(map[string]interface{}{"name": users.Name, "age": users.Age}) } func search(db *gorm.DB) []User { var user []User // 同じ位置にいるリストを取得 db.Raw("SELECT * FROM users").Scan(&user) return user } 説明 routing/main.go type User struct { gorm.Model Name string `json:"name"` Age int `json:"age"` } User(単数形)はMySQLのテーブル名「Users(複数形)」単数名にする必要がある Name,Ageは先頭大文字である必要がある。 json:"name"はリクエストボディに関連させる名前。 main.go package main import ( "github.com/labstack/echo" "src/routing" ) func main() { e := echo.New() // routing e.GET("/user",routing.BaseAPI_GET()) e.POST("/user",routing.BaseAPI_POST()) e.Logger.Fatal(e.StartTLS(":443", "/crt/live/<あなたのドメイン名>/fullchain.pem", "/crt/live/<あなたのドメイン名>/privkey.pem")) } HTTPでよいなら docker-compose.yml version: "3" services: golang: build: ./golang/ image: image_golang container_name: container_api volumes: - ./src:/go/src # 証明書を/go/src/crtへ # - /etc/letsencrypt:/go/src/crt <- 削除 ports: # - "443:443" <- 削除 - "8080:8080" <- 追加 tty: true mysql: # platform: linux/x86_64 #AppleSiliconを使用時,必要 build: ./mysql/ image: image_mysql container_name: container_db volumes: - ./mysql/db:/docker-entrypoint-initdb.d #初期データをマウントする場所 environment: # コンテナ内のMySQLを起動する際のパスワードを設定 - MYSQL_DATABASE=golang # 作成するデータベース名 - MYSQL_USER=akidon # 作業ユーザー名(任意の値) - MYSQL_PASSWORD=12345 # 作業ユーザーのパスワード(任意の値) - MYSQL_ROOT_PASSWORD=root # rootユーザーのパスワード(デフォルトでは「root」) ports: - "3306:3306" tty: true main.go // e.Logger.Fatal(e.StartTLS(":443", "/crt/live/<あなたのドメイン名>/fullchain.pem", "/crt/live/<あなたのドメイン名>/privkey.pem")) e.Logger.Fatal(e.Start(":8080")) // <- 追加 オレオレ証明書では crtに ・ myself.csr ・ myself.key ・ myself.crt がある場合 main.go // e.Logger.Fatal(e.StartTLS(":443", "./crt/live/<あなたのドメイン名>/fullchain.pem", "./crt/live/<あなたのドメイン名>/privkey.pem")) e.Logger.Fatal(e.StartTLS(":443", "crt/myself.crt", "crt/myself.key")) // <- 追加 動かす $ cd ../プロジェクト名/server/docker (再ビルドしても変更されない場合はキャッシュが残っている可能性がある為,全削除) (注意) $ docker rm -f `docker ps -a -q` (ビルドする) $ docker compose up -d --build (コンテナ内に入る)**1分ぐらい待つ(MySQLの初期設定の完了に時間がかかる)** $ docker-compose exec mysql bash root@コンテナ番号:# exit $ docker-compose exec golang bash (go mod init フォルダ名) root@コンテナ番号:/go/src# go mod init src root@コンテナ番号:/go/src# go run main.go MySQLの中を覗く % docker-compose exec mysql bash root@コンテナ番号:/# mysql -u root -p -h 127.0.0.1 (パスワードの入力を求められるので「root」を入力) -> root (現在存在するアカウントの確認) (hostに「%」がついてるか確認) mysql> select host,user from mysql.user; +-----------+------------------+ | host | user | +-----------+------------------+ | % | akidon | | % | root | | localhost | mysql.infoschema | | localhost | mysql.session | | localhost | mysql.sys | | localhost | root | +-----------+------------------+ (ついていない場合は以下コードで追加できたはず) mysql> grant all privileges on golang.* to 'akidon'@'%'; mysql> show databases; +--------------------+ | Database | +--------------------+ | golang | <- 作成できてるか確認 | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.06 sec) mysql> use golang; mysql> show tables; +------------------+ | Tables_in_golang | +------------------+ | users | <- 作成できてるか確認 +------------------+ 1 row in set (0.01 sec) mysql> SELECT * FROM `users`; +----+---------+------+------------+------------+------------+ | id | name | age | created_at | updated_at | deleted_at | +----+---------+------+------------+------------+------------+ | 1 | testKun | 21 | NULL | NULL | NULL | +----+---------+------+------------+------------+------------+ 1 row in set (0.00 sec) この時点でエラーが起きた場合 ・src/main.go 27行目のcontainer_dbはdocker-composeで指定したコンテナ名を指定しているか。 ・ポート解放してるか ・データベース(テーブル)が正しく作成されているか(今回ならgolang) ・大文字小文字の区別を無視していないか ・go mod init src したか?(この辺は理解不足で間違っている場合がある。src以下のファイルをサブパッケージとして参照できるようにする??) ・docker起動できているか以下コマンドで確認 # 動いているdocker一覧表示 docker-compose ps # 作成した全てのdocker一覧表示 docker-compose ps -a 豆知識 main.goの内容を変更してもDocker再buildする必要はない SequelAce GoENV GO111MODULE="" GOARCH="arm64" GOBIN="" GOCACHE="/root/.cache/go-build" GOENV="/root/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="arm64" GOHOSTOS="linux" GOINSECURE="" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/root/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/linux_arm64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="/go/src/go.mod" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build147035606=/tmp/go-build -gno-record-gcc-switches" 参考記事 docker-compose upって何? Go言語の依存モジュール管理ツール Modules の使い方 他多数
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLのLOAD DATA INFLEコマンドでファイルをインポートする

はじめに 担当している案件でMySQLで大量(10万件規模)のデータをinsertする必要があったため、 LOAD DATA INFILE コマンドでデータをインポートした際のナレッジや調査過程をまとめました。 案件で使用していたフレームワークがLaravelだったため、Laravel寄りのリンクが多くなっていますが、 他の言語/フレームワークでも、SQLを直接発行出来る機能があれば、代用は可能かと思います。 またMySQL以外でもOracleでも同様のコマンドがあるので、DBをOracleに変えた場合でも同じ実装は可能かと思います。 注意点 MySQLの起動オプションにlocal_infileを追加 MySQLの起動オプションにlocal_infileの設定を追加します。 以下のファイルに下記のように設定を追加してください。 /etc/mysql/conf.d/my.cnf local_infile=true mysqlコマンドの場合は上記のオプションを引数に追加して起動しましょう。 configファイルに追記した場合は、MySQLのサービスの再起動も忘れずに! デバッグ/エラー解析 LOAD DATA INFILE コマンドは、MySQL側のインポート機能を直接呼び出す仕組みのため、 SELECT文やINSERT文のSQLの発行時のようにアプリケーション側のログにエラー内容が出力されることがありません。 そのため、デバッグやエラー解析は困難を極めます。 インポート先のテーブル名やカラム定義、インポートするファイル名やファイルパス等は念入りに確認しておいた方が良さそうです。 意外にtypoしていたりすると、気付かずハマります(苦笑) 参考 LaravelでデータをDBに保存したいときのメモリ不足をなんとかする LaravelでLOAD DATA LOCAL INFILEできない Laravel ExcelパッケージでCSVデータをDBへ一括登録する方法 REPLACEとAUTO_INCREMENTを使用してLOADDATAINFILEを実行しようとしています 【MySQL】LOAD DATA INFILE でCSVデータをインポートしたい MySQLの「load data LOCAL infile」の「LOCAL」って何?どこ? MySQL LOAD DATA LOCAL INFILE で特定列を指定してインポートする
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む