20200320のMySQLに関する記事は7件です。

MySQL for mac エラー編

MySQLをインストールする手順は下記を参考に導入しました
Mac へ MySQL を Homebrew でインストールする手順

動作確認

  • 動作確認をすると接続エラーが!
$ mysql -uroot -p
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

どうやらファイルが/tmp/mysql.sockファイルがないためらしいのでファイルを作成する

$ sudo touch /tmp/mysql.sock
# 所有権限を変更する
$ sudo chown -R _mysql:_mysql /usr/local/var/mysql
  • MySQLサーバーを再起動
$ sudo mysql.server start
... ERROR! The server quit without updating PID file (/usr/local/var/mysql/xxxxx.local.pid).
  • またもファイルがないと怒られるのでファイルを作成する
$ sudo touch /usr/local/var/mysql/xxxxx.local.pid
$ sudo mysql.server start!
Starting MySQL
. SUCCESS!
  • 改めて動作確認
$ mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.19 Homebrew

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

ドライバ接続エラー

Unable to load authentication plugin 'caching_sha2_password'.

  • my.confに下記を追加
/usr/local/etc/my.conf
default_authentication_plugin=mysql_native_password
# サーバー再起動
$ sudo mysql.server restart
# ログイン
$ mysql -u root -p
# ユーザーを作成(mysql_native_passwordで作成される)
mysql> CREATE USER 'user_name' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> select host,user from mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| %         | user_name        |
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |
+-----------+------------------+
5 rows in set (0.01 sec)

persistent-mysqlパッケージインストール時のエラー

  • 'pcre.h' file not foundこんなエラーが出たのでpcreをインストール
pcre-light        > /private/var/folders/73/b39jpnl178xb4sgf8wm2n0yc0000gn/T/stack-13f48f3d3c1d2941/pcre-light-0.4.1.0/Base.hsc:103:10: fatal error: 'pcre.h' file not found
pcre-light        > #include <pcre.h>
pcre-light        >          ^~~~~~~~
# ↑こんなエラー出たのでpcreをインストール
$ brew install pcre
  • 再度ビルドチャレンジするも再びエラーに見舞われる
$ stack build
# こんなエラー
mysql             > Configuring mysql-0.1.7...
mysql             > setup: Missing dependencies on foreign libraries:
mysql             > * Missing (or bad) C libraries: ssl, crypto
mysql             > This problem can usually be solved by installing the system packages that
mysql             > provide these libraries (you may need the "-dev" versions). If the libraries
mysql             > are already installed but in a non-standard location then you can use the
mysql             > flags --extra-include-dirs= and --extra-lib-dirs= to specify where they are.If
mysql             > the library files do exist, it may contain errors that are caught by the C
mysql             > compiler at the preprocessing stage. In this case you can re-run configure
mysql             > with the verbosity flag -v3 to see the error messages.
  • Cのライブラリがないか、パスが間違ってるんじゃないかというエラーメッセージが出ている
# ライブラリをインストール
$ brew install icu4c
Warning: icu4c 64.2 is already installed and up-to-date
To reinstall 64.2, run `brew reinstall icu4c`
$ brew install openssl
Updating Homebrew...
Warning: openssl@1.1 1.1.1d is already installed and up-to-date
To reinstall 1.1.1d, run `brew reinstall openssl@1.1`
# 両方ともインストールされていました
  • Cライブラリのパスを設定
~/.stack/config.yaml
extra-include-dirs:
- /usr/local/opt/icu4c/include
- /usr/local/opt/openssl/include

extra-lib-dirs:
- /usr/local/opt/icu4c/lib
- /usr/local/opt/openssl/lib
  • 再度ビルドチャレンジ
$ stack build
> build (lib + exe)

参考
Aelve Guide | Haskell

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQLのトランザクションと分離レベル

非常に基本的なことなのですが、データベースのトランザクションの分離レベルの話をしていてちょっと混乱してしまったことがありました。ので、基本に立ち返り、トランザクション周りを整理しようと思ったわけです。

環境

本記事の環境は以下のとおりです。

  • MySQL on docker
    • docker client version : 19.03.8
    • docker engine version : 19.03.8
    • mysql image version : 8.0.18

トランザクション制御のステートメント

MySQLでは次のステートメントでトランザクションを制御できます。

  • START TRANSACTION か、 BEGIN により新しいトランザクションを開始
  • COMMIT でトランザクションをコミットし、変更を永続化
  • ROLLBACK でトランザクションをロールバックし、変更を取り消す

実際に使ってみるとこうなります。

mysql> BEGIN;
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT * FROM books;
+----+-------------------------+--------------------------+---------------+
| id | name                    | publisher                | author        |
+----+-------------------------+--------------------------+---------------+
|  1 | Refactoring 2nd Edition | OBJECT TECHNOLOGY SERIES | Martin Fowler |
|  2 | Test Driven Development | Addison-Wesley           | Kent Beck     |
+----+-------------------------+--------------------------+---------------+
2 rows in set (0.00 sec)

mysql> DELETE FROM books WHERE id = 2;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM books;
+----+-------------------------+--------------------------+---------------+
| id | name                    | publisher                | author        |
+----+-------------------------+--------------------------+---------------+
|  1 | Refactoring 2nd Edition | OBJECT TECHNOLOGY SERIES | Martin Fowler |
+----+-------------------------+--------------------------+---------------+
1 row in set (0.00 sec)

mysql> ROLLBACK;
Query OK, 0 rows affected (0.02 sec)

mysql> SELECT * FROM books;
+----+-------------------------+--------------------------+---------------+
| id | name                    | publisher                | author        |
+----+-------------------------+--------------------------+---------------+
|  1 | Refactoring 2nd Edition | OBJECT TECHNOLOGY SERIES | Martin Fowler |
|  2 | Test Driven Development | Addison-Wesley           | Kent Beck     |
+----+-------------------------+--------------------------+---------------+
2 rows in set (0.00 sec)
Query OK, 0 rows affected (0.02 sec)

分離レベルとリード現象

トランザクションには分離レベルを設定できます。分離レベルとは、複数のトランザクションが互いに与える影響の度合いのことで、ACID特性のI(隔離性)に該当します。一般的なデータベースシステムでは複数の分離レベルを設定値として持っていてトランザクションごとに分離レベルを設定できます。

分離レベルを変更するには SET TRANSACTION ステートメントを使用します。基本的な使い方は次のとおりです。[level] にはいずれかの分離レベルを指定します。詳しくは公式のドキュメントを参照してください。(https://dev.mysql.com/doc/refman/5.6/ja/set-transaction.html)

SET TRANSACTION ISOLATION LEVEL [level]

MySQLで設定できる分離レベルは4つになります。以下の順序はMySQLのドキュメントに示されている使用される頻度順です。

  1. REPEATABLE READ
  2. READ COMMITTED
  3. READ UNCOMMITTED
  4. SERIALIZABLE

それぞれの分離レベルでは異なるリード現象が発生します。リード現象とは、同時に走る2つ以上のトランザクションが互いに変更したデータを読み取る時の現象のことです。ANSI/ISO standard SQL 92 では次に示す3つのリード現象が定義されています。

名前 概要
ダーティーリード 別のトランザクション内でコミットされていないデータを読み取る
ノンリピータブルリード トランザクション内で2回以上同じ行を取得した際、行の値が異なる結果を読み取る
ファントムリード トランザクション内で2回以上同じ検索結果を取得した際、行が追加・削除された結果を読み取る

MySQLでの分離レベルとリード現象の対応は次のとおりです。

分離レベル ダーティーリード ノンリピータブルリード ファントムリード
READ UNCOMMITTED
READ COMMITTED ×
REPEATABLE READ × × ×
SERIALIZABLE × × ×

※ × 発生しない ○ 発生する

ダーティーリード

ダーティーリードは別のトランザクション内でコミットされていないデータを読み取る現象です。他のリード現象と比べるとトランザクションの隔離性が一番低い現象です。分離レベルが READ UNCOMMITTED の時にダーティーリードが発生します。実際にやってみた結果を次に示します。

/* Transaction 1 */
mysql> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Query OK, 0 rows affected (0.00 sec)

/* Transaction 1 */
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

/* Transaction 1 */
mysql> SELECT * FROM books;
+----+-------------------------+--------------------------+---------------+
| id | name                    | publisher                | author        |
+----+-------------------------+--------------------------+---------------+
|  1 | Refactoring 2nd Edition | OBJECT TECHNOLOGY SERIES | Martin Fowler |
|  2 | Test Driven Development | Addison-Wesley           | Kent Beck     |
|  3 | Building Microservices  | O'Reilly Media           | Sam Newman    |
+----+-------------------------+--------------------------+---------------+
3 rows in set (0.00 sec)

                            /* Transaction 2 */
                            mysql> BEGIN;
                            Query OK, 0 rows affected (0.00 sec)

                            /* Transaction 2 */
                            mysql> DELETE FROM books WHERE id = 3;
                            Query OK, 1 row affected (0.01 sec)

/* Transaction 1 */
mysql> SELECT * FROM books;
+----+-------------------------+--------------------------+---------------+
| id | name                    | publisher                | author        |
+----+-------------------------+--------------------------+---------------+
|  1 | Refactoring 2nd Edition | OBJECT TECHNOLOGY SERIES | Martin Fowler |
|  2 | Test Driven Development | Addison-Wesley           | Kent Beck     |
+----+-------------------------+--------------------------+---------------+
2 rows in set (0.00 sec)

ノンリピータブルリード

ノンリピータブルリードはトランザクション内で2回以上同じ行を取得した際、行の値が異なる結果を読み取る現象です。分離レベルが READ COMMITTED, READ UNCOMMITTED の時にノンリピータブルリードが発生します。ダーティーリードと似たような現象ですが、ダーティーリードではコミットされていないデータを読み取る点に対し、ノンリピータブルリードではコミットされたデータを読み取る点で動作が異なります。

実際にやってみた結果を次に示します。

/* Transaction 1 */
mysql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)

/* Transaction 1 */
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

/* Transaction 1 */
mysql> SELECT * FROM customers;
+----+--------------+---------+
| id | name         | version |
+----+--------------+---------+
|  1 | Aurel Croson |       4 |
+----+--------------+---------+
1 row in set (0.00 sec)

                            /* Transaction 2 */
                            mysql> BEGIN;
                            Query OK, 0 rows affected (0.00 sec)

                            /* Transaction 2 */
                            mysql> UPDATE customers SET version = 5 WHERE id = 1;
                            Query OK, 1 row affected (0.00 sec)
                            Rows matched: 1  Changed: 1  Warnings: 0

                            /* Transaction 2 */
                            mysql> COMMIT;
                            Query OK, 0 rows affected (0.01 sec)

/* Transaction 1 */
mysql> SELECT * FROM customers;
+----+--------------+---------+
| id | name         | version |
+----+--------------+---------+
|  1 | Aurel Croson |       5 |
+----+--------------+---------+
1 row in set (0.00 sec)

ファントムリード

ファントムリードはトランザクション内で2回以上同じ検索結果を取得した際、行が追加・削除された結果を読み取る現象です。分離レベルが READ COMMITTED, READ UNCOMMITTED の時にファントムリードが発生します。(※MySQLではREPEATABLE READ の分離レベルでもファントムリードが発生しません。)

実際にやってみた結果を次に示します。

/* Transaction 1 */
mysql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)

/* Transaction 1 */
mysql> BEGIN;
Query OK, 0 rows affected (0.01 sec)

/* Transaction 1 */
mysql> SELECT * FROM customers;
+----+--------------+---------+
| id | name         | version |
+----+--------------+---------+
|  1 | Aurel Croson |       5 |
+----+--------------+---------+
1 row in set (0.00 sec)

                            /* Transaction 2 */
                            mysql> BEGIN;
                            Query OK, 0 rows affected (0.00 sec)

                            /* Transaction 2 */
                            mysql> INSERT INTO customers VALUES (2, 'Griz Dradey', 1);
                            Query OK, 1 row affected (0.00 sec)

                            /* Transaction 2 */
                            mysql> COMMIT;
                            Query OK, 0 rows affected (0.02 sec)

/* Transaction 1 */
mysql> SELECT * FROM customers;
+----+--------------+---------+
| id | name         | version |
+----+--------------+---------+
|  1 | Aurel Croson |       5 |
|  2 | Griz Dradey  |       1 |
+----+--------------+---------+
2 rows in set (0.00 sec)

おわりに

分離レベルの事を調査していたらリード現象になるものを知り、思っていたより整理に時間がかかりました。データベースにはまだまだ自分の知らない領域があるので引き続き調査して行きたいと思っています。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel+Mysql+Vue.jsの開発環境をDockerで構築

はじめに

Laravel+Mysql+Vue.jsでSPAのWebアプリケーション作成の勉強をしたくて、Dockerで開発環境構築をしました。
開発の常で、開発環境構築に苦戦したので備忘録を兼ねて構築手順を記述します。
記載内容に誤り等ございましたら、ご指摘をよろしくお願いいたします。

開発環境

$ docker --version
Docker version 19.03.8, build afacb8b

$ docker-compose --version
docker-compose version 1.25.4, build 8d51620a

$ php artisan --version
Laravel Framework 7.2.0

$ mysql --version
mysql  Ver 14.14 Distrib 5.7.29, for Linux (x86_64) using  EditLine wrapper

$ npm list vue
`-- vue@2.6.11 

参考

ディレクトリ構成

project
├ docker-compose.yml
├ docker
│  ├ php
│  │  ├ php.ini
│  │  └ Dockerfile
│  └ nginx
│    └ default.conf
└ server

手順

1. ファイルを準備

以下のファイルを作成します。

  • Dockerfile
  • docker-compose.yml
  • php.ini
  • default.conf
project/docker/php/Dockerfile
FROM php:7.4.1-fpm
COPY php.ini /usr/local/etc/php/

RUN apt-get update \
  && apt-get install -y zlib1g-dev libzip-dev zip mariadb-client-10.3 libpng-dev libjpeg-dev curl wget \
  && docker-php-ext-install zip pdo_mysql

# nodejs install
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get install -y nodejs

# Composer install
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php -r "if (hash_file('SHA384', 'composer-setup.php') === '$(wget -q -O - https://composer.github.io/installer.sig)') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer

ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin
WORKDIR /var/www
RUN composer global require "laravel/installer"

mysql-clientのパッケージは削除されているので注意。

project/dockerfile-compose.yml
version: '3'
services:
  php:
    container_name: php
    build: ./docker/php
    volumes:
      - ./server:/var/www
    depends_on:
      - db
  nginx:
    image: nginx
    container_name: nginx
    ports:
      - 80:80
    volumes:
      - ./server:/var/www
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - php
  db:
    image: mysql:5.7
    restart: always
    container_name: db-host
    environment:
      MYSQL_ROOT_PASSWORD: yourpassword
      MYSQL_DATABASE: phpapp_db
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
    volumes:
      - ./docker/db/data:/var/lib/mysql
      - ./docker/db/my.conf:/etc/mysql/conf.d/my.cnf
      - ./docker/db/sql:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306
project/docker/php/php.ini
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
project/docker/nginx/default.conf
server {
  listen 80;
    index index.php index.html;
    root /var/www/public;

  location / {
    root /var/www/public;
    index  index.html index.php;
    }

  location ~ \.php$ {

    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    include fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
  }
 }

2. dockerコンテナを立ち上げる

$ docker-compose build
$ docker-compose up -d

3. phpコンテナに入ってlaravelプロジェクトを作成する

$ docker-compose exec php bash
$ laravel new

4. dockerコンテナを一旦停止する

$ docker-compose down

5. .envファイルを編集する

以下のように無いパラメーターは追加し、すでに記述されているパラメーターは修正する。

project/server/.env
DB_CONNECTION=mysql
DB_HOST=db-host
DB_PORT=3306
DB_DATABASE=phpapp_db
DB_USERNAME=root
DB_PASSWORD=yourpassword

6. コンテナを立ち上げる

$ docker-compose up -d

7. ローカルホストにつながることを確認する

ブラウザから以下のURLにアクセスして正常に接続できることを確認する。

正常に接続できれば以下のような画面が表示される。

Built_laravel_environment_1

8. migrateが実行できることを確認する

phpコンテナに入ってmigrateを実行する。

$ docker-compose exec php bash
$ php artisan migrate

migrateが失敗する場合は以下の記事等を参考にして頂くと良いと思います。

9. Vue.jsの導入

npmでvueのパッケージをインストール。

$ npm install
$ npm install -D vue

vueのパッケージがインストールできていることを確認。

$ docker-compose exec php bash
$ npm list vue

開発環境構築は以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DB Containerに大容量のデータをインポートしたい場合は、コンテナに入ってから実行する

はじめに

WSL2で、ホストからMysql コンテナに3GBのデータをインポートしようとした際、詰まったので共有します

結論

//dumpファイルをMysqlコンテナにコピー
docker cp [import file name] [container id]:[container file path]

//Mysqlコマンドでログイン
mysql -u [user name] -p [db name]

//Sourceコマンドでインポート
source [container file path]

詳細

最初、コンテナの外からインポート実行しましたが、コマンド実行中のまま止まってました。

docker exec -i mysql -u [user name] -p [db name] > [import file path]

処理を止めてDBを見にいっても、何も書かれていないので動いていないと判断。

インポートファイルのサイズが大きい場合、Mysqlの中に入って実行しない駄目っぽい記事を見つけ、解消。

おわりに

再度Importファイルを指定しようとしたら、サイズが0になってたので、以後コピーしてから実施しよう。。
Exportしなおすのに時間を浪費してしまった。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CentOS7でSupersetのDBをsqliteからMySQLにお引越し

経緯

CentOS7にSupersetを入れて、可視化していた。
Superset設定格納DBにMySQLを使っていたつもりがsqliteを使っていたので乗り換えた。
その手順を日本語で解説してるサイトが無かったのとアジア語特有の落とし穴があったのでメモ

読者前提

CentosにSuperset入れてそのまま使ってた人
可視化ツール使いたいだけでサーバコマンドは苦手な人

所要時間

30分くらい?
Superset単品用途でDBを作って使ってた人(デフォルト設定)は
特に難しくない

手順

(前提:参考にしたのはこのサイト
https://medium.com/@acmicrox/superset-database-migration-from-sqlite-to-mysql-c882e5ab9349)

目次
1.MySQLを入れてDBとユーザを作る
2.sqliteのDBから再構築用SQLを作る
3.Superset_config.pyファイルを作って設定
4.MySQL上でdb upgradeしてSQL実行
5.SqliteとMySQLでデータ比較
6.Superset設定再読み込み
7.Supersetの稼働確認

1.MySQLを入れてDBとユーザを作る

元々MySQL入ってる人はそのままで良い。

1-1.MySQL公式サイト↓よりLinux 7版のrpm名を見つけてコピー

OS名の下にある、mysql*.rpmがそれです。
https://dev.mysql.com/downloads/repo/yum/

1-2.rpmファイルのダウンロード

$ yum localinstall http://dev.mysql.com/get/さっきコピーしたrpm名

1-3.rpmファイルの展開

$ yum install -y mysql-community-server

1-4.自動起動設定して起動

$ systemctl enable mysqld
$ systemctl start mysqld

1-5.ユーザ登録してログイン

デフォルトパスワードを取得

$ cat /var/log/mysqld.log | grep 'temporary password' | awk -F ': ' '{print $NF}'

ログイン。パスワードを聞かれるので、一つ前で取得したパスワードを入力

$ mysql -u root -p

mysqlが起動できたら、パスワードを変更
ついでに権限付与、DB作成、文字コードの確認。

> SET PASSWORD = PASSWORD('8文字以上英大小文字数字記号込のパスワード')
> GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost'   IDENTIFIED BY '↑と同じパスワード' WITH GRANT OPTION;
> SHOW VARIABLES LIKE "chara%";

文字コードは、Supersetを扱うときは下記の2つ以外はutf8に統一するのが無難。
character_set_filesystem
character_sets_dir

utf8mb4ではdb upgradeがエラーになった。
(が、文字コードが原因とは書いてないので突き止めるのに時間かかった)

1-6.文字コード変える(必要な人だけ)

NGの人はmysqlから一旦出る

> quit;

mysqlの設定ファイルを書き換える

$ vi /etc/my.cnf

以下をファイルの末尾に追記。
大文字G入力でファイル末尾に移動、$で行末尾に移動、iで入力モードにして
Enterで改行し、↓の1行を必要なだけコピペ追加。
character_1-5でutfじゃなかったやつ=utf8

で、追加と編集し終わったら、Escキー押して:キー押したらwqと入力してEnterでファイル閉じる。
そして↑で追記した内容をrestartでmysqldに反映して起動。

$ systemctl restart mysqld 
$ mysql

1-7.DBを作る

ここでトチ狂ってutf8mb4で作ってはいけない。
superset db upgradeがtoo long keyのエラーになり実行できなくなる。
またfabmanagerでユーザを作ってしまうとあとあとalembic_versionのエラーになり詰まるので自分では作らないこと。

>CREATE DATABASE superset CHARACTER SET utf8 COLLATE utf8_bin;
>quit;

2.sqliteのDBから再構築用SQLを作る

2-1.sqliteからSQLを作成

必要に応じて# locate superset.dbで、sqliteのsuperset.dbの位置を確認。
ほにゃらら/.superset/superset.dbになってるはず。
なので↓のコマンドでsqlを作る。この時点のsqlはsqlite仕様。

$ sqlite3 ほにゃらら/.superset/superset.db .dump > superset_statements.sql

2-2.SQLをMySQL仕様に編集する。
先ほど作ったsqlを編集する。

$ vi superset_statements.sql

↓の5文を1行ずつ実行する

:%s/PRAGMA foreign_keys=OFF;/SET FOREIGN_KEY_CHECKS = 0;/g
:%s/BEGIN TRANSACTION;/START RANSACTION;/g
:%s/INSERT INTO "/INSERT INTO /
:%s/" VALUES (/ VALUES (/g
:%s/\\"/\\\\"/g

CREATE *のSQLは、superset自身に正しく構築させるため
sqlから削除する。INSERTだけになるようにする。
↓の文でfindを行い、表示された行をDeleteで消す。

/CREATE

上方向検索なら?CREATE,次を探すならnキー、前を探すならNキーで探せる。

SQLが準備できました。

3.Superset_config.pyファイルを作って設定

デフォルトではsuperset_config.pyは存在しない。
元々のsuperset/config.pyは直接いじっちゃいけない。
設定を上書きするには作ってファイルの在りかをsupersetにわかる変数に設定してあげる必要がある。
一旦↓ではusr/localに置いてるけど、何処でもいい。

$ vi /usr/local/superset_config.py

iで編集モードにして
以下の1文を設定する。mysql://ユーザ名:パスワード@ホスト名/データベース名の表記ルール。

SQLALCHEMY_DATABASE_URI = 'mysql://root:1-5で作ったパスワード@localhost/superset'

書き終えたら、Escキー→:キー→wq記入→Enterキーでファイルを閉じ、
supersetの分かる変数にファイルの置き場所を指定してあげる。
PYTHONPATHという変数なら分かるとのこと。

$ export PYTHONPATH="/usr/local/:$PYTHONPATH"

またサーバ再起動ごとに設定する手間を省くため、
起動時に読み込む設定を記載する.bash_profileファイルに変数を追記する。

$ vi ~/.bash_profile

iキー→末尾に行を追加し↓の1文をコピペ→Escキー→:キー→wq記入→Enterキーでファイルを閉じる

export PYTHONPATH="/usr/local/:$PYTHONPATH"

4.MySQL上でdb upgradeしてSQL実行

cd ほにゃららでsupersetを起動して↓のコマンドを実行する
configファイルから読み込み直してDBを整備してくれる。

$ superset db upgrade 

普通は10秒くらいで終わる。私は最初に文字コードを間違えエラーになった。→末尾のエラー1参照
次に↓を実行。

$ cd
$ mysql -h ホスト名 -u root -p -D superset < superset_statements.sql

普通はうまくいくらしい。私はエラーになった。→末尾のエラー2参照

5.SqliteとMySQLでデータ比較

Sqliteから全テーブル全行の値を抽出しMySQLと比較する。

5-1.件数比較。飛ばしてデータ比較でも良い。

$mysql superset
>select 'テーブル名',count(*) from テーブル名 UNION
...;
>select 'テーブル名',count(*) from テーブル名;

で取得。

>quit;

sqliteは

$sqlite3 ほにゃらら/.superset/supserset.db
>mysqlで実行したcountSQLと同じ物を実行
>.quit

で、比較する。一致していれば完璧。差分が有れば原因を突き止め、想定内かを確認
数が合っていてもデータの項目との配置ズレが起きていたら動かない。
なので、面倒でもデータ差分を確認する。

5-2.データを比較

書き疲れたのでちょっと待って。。
あとで編集します

6.Superset設定再読み込み

systemctlでsupersetを管理している人は↓でリスタート。

$ systemctl restart superset

そうでない人はcdでsupersetの実行環境に入り↓を実行

$superset run server -d

7.Supersetの稼働確認

supersetのグラフが正しく表示されていることを確認する。
データの数や内容は、sql上で確認しているので描画されるか、だけ確認しておけばいい。

Appendix.陥ったエラー群書き溜めメモ

エラー1:superset db upgradeでToo long keyというエラーが出る

mysqlの文字型が問題と思われる。
supersetに使うdbについてはutf8mb4は諦めて、
既存との共存ではなく新dbをCREATEするといい。CREATE時の設定は本文参照。

作っちゃったのを変えたい人は、面倒でも↓のsqlを作って実行するか、
中に入ってるデータを退避してdbを再作成する。再作成の方がおすすめ。

ALTER DATABASE db_name CHARACTER SET utf8 COLLATE utf8_bin;
ALTER TABLE table_name CONVERT TO character SET utf8 COLLATE utf8_bin;
ALTER TABLE table_name CHANGE column_name column_name 型桁 CHARACTER SET utf8 COLLATE utf8_bin;

もちろん、テーブルalter文はテーブルの分だけ、alter項目文は項目の分だけ作る。

エラー2:sqlの実行で項目数が合わないというエラーが出る

sqliteとMySQLのSupersetメタデータ用テーブルのレイアウトを比較。

1.MYSQLから取得

$ mysql superset

>select TABLE_NAME, COLUMN_NAME, Null, Key, Default from information_schema.COLUMNS where TABLE_SCHEMA = 'projectdb';

2.sqliteから取得

$sqlite3 ほにゃらら/.superset/superset.db

>.schema

3.出てきた内容をExcelなりGoogleスプレッドシートなりでテーブル名でkey合わせして比較してみる。
4.出てきた差分に合わせてINSERT SQLを改修してやる。
 例えばvi superset_statement.sqlで↓のようなコマンドを実行する。

:%s/INSERT INTO テーブル名 VALUES/INSERT INTO テーブル名 (項目名群) VALUES/g

普通はここで転ぶことはないらしい、が、
Superset v0.28.0利用者の私は転んだ。
sliceテーブルのdatasource_idとslice_idの項目がMySQL側に表示されているが
Sqlite側に無い・・Null許可やKey設定、SupersetPGMのPythonコードを見る限り
datasource_idもslice_idもNullで良さげ。
なので、INSERT文へINSERT項目名を載せ直して再実行した。
OSS使うと、こういう謎な動作をある程度自分で解析せねばならんところが面倒。
ん?いやOSSだけじゃねぇな。製品でも同じだな。よくバグ引いてベンダーとギャアギャァ喧嘩してたな。
頻度の違いだな。OSSはまだ内部構造が自分で見えるぶん直せるが、製品は詰む。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【準備編】Vagrantで立てたCentOSにLaravel環境を構築し弄り回す…その前に。

【導入編】の続きです。

下記記事の続きを想定しております。
まずはLaravelのサンプル画面が立ち上がった時点から開始
https://qiita.com/katsuhito_01/items/439e3af4cea8ff00832c

MySQLをインストール

Laravelで用いるデータベースを構築。
MySQLでもPostgressでも何でもOK。今回はとりあえずMySQLを使用。

mariaDBを削除

CentOS7の場合、デフォルトでMySQL互換のmariaDBがインストールされている可能性がある。
競合を避けるため、念のため削除しておく。

# sudo yum remove mariadb-libs
# sudo rm -rf /var/lib/mysql/

yum リポジトリの追加

yumでインストールするため、MySQL公式のyumリポジトリを追加する。

# sudo yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm

インストールの実行

yumインストールを実行。実行後、念のためMySQLのバージョンを確認してみる。

# sudo yum -y install mysql-community-server
# mysql --version
mysql  Ver 14.14 Distrib 5.7.29, for Linux (x86_64) using  EditLine wrapper

MySQLの起動

インストールの確認ができたら、MySQLを起動。
ついでにマシン起動時に自動的に立ち上がるようにしてしまう。

# sudo systemctl start mysqld.service
# sudo systemctl enable mysqld.service

初期パスワードを確認

セキュリティ設定のための初期パスワードを確認。どこかにメモっておく。

# view /var/log/mysqld.log
[Note] A temporary password is generated for root@localhost: 初期パスワード

MySQLのセキュリティ設定

ログインするためにセキュリティ設定をしておく。
まず初期パスワードが聞かれるので、メモっておいたパスワードを入力。

# mysql_secure_installation
Securing the MySQL server deployment.

Enter password for user root:

新しいパスワードを入力し、再度同じパスワードを入力する。
※わかりやすいパスワードだと怒られます。

その後は対話式で色々設定を聞かれます。必要に応じてYかNかを入力していけば完了。
今回は全部Yでやりました。

The existing password for the user account root has expired. Please set a new password.

New password:

Re-enter new password:

ログインし使用するデータベースを作っておく

設定したパスワードでログインできるか確認。
ログイン出来たら、データベースをつくっておく。

# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.7.29 MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> CREATE DATABASE mypage01_db;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mypage01_db        |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql>

.envファイルに設定情報を記述

Laravelプロジェクトディレクトリ直下に.envファイルがあるので、中にDB情報を記述。
(無い場合は、.env.exampleをコピーして作成)

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mypage01_db
DB_USERNAME=root
DB_PASSWORD=root

VagrantのhomeディレクトリをSambaで共有

今回はWindows上にvagrantでCentOS7を立て、CentOS7上にLaravel環境を構築している。
Windows側からエディタで資材を弄りまわしたいので、Sambaで何とかする。
Vagrantfileのsynced_folderも考えたが、いかんせん同期が遅く動作が重い…

Sambaをインストール

とりあえずsambaをインストールする。

# sudo yum install samba

Configをいじる

# sudo vi /etc/samba/smb.conf
[global]
        workgroup = SAMBA
        security = user

        passdb backend = tdbsam

        printing = cups
        printcap name = cups
        load printers = yes
        cups options = raw
        hosts allow = 127. 192.168.33. # vagrant環境に合わせてよしなに設定
        unix extensions = no      # 追加
        wide links = yes               # 追加
[homes]
        comment = Home Directories
        valid users = %S, %D%w%S
        browseable = No
        read only = No
        inherit acls = Yes

[printers]
        comment = All Printers
        path = /var/tmp
        printable = Yes
        create mask = 0600
        browseable = No

[print$]
        comment = Printer Drivers
        path = /var/lib/samba/drivers
        write list = @printadmin root
        force group = @printadmin
        create mask = 0664
        directory mask = 0775

アクセスパスワードの設定

Windowsからアクセスする際のパスワードを設定。
特にrootパスワードと同じでも問題ないので、よしなに設定。

# sudo pdbedit -a vagrant
# new password:
# retype new password:

Samba起動&自動起動設定

Sambaを立ち上げつつ、マシン起動時に自動で立ち上がるようにしておく。

# sudo systemctl enable smb
# sudo systemctl start smb

Windowsエクスプローラーからアクセス

Windows側のエクスプローラーより、\\192.168.33.10\vagrantでアクセス。
CentOS7のvagrantホームディレクトリに入れる。

Windowsコマンドプロンプトで、適当なドライブに設定してしまってもよいかも。

$ net use Z: \\192.168.33.10\vagrant

シンボリックリンクの作成

CentOS7のvagrantホームディレクトリに、以下シンボリックリンクを作成。

# cd /home/vagrant
# ln -s /var/www/html/ html

これでWindows側よりLaravelのドキュメントルートへアクセスできるようになる。
あとはPHPSTORMやATOMなど、お好きなエディタで開けば弄り回せるようになる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker + django + Nginx + MySQL を理解する

Windows 10 Professional
Docker Desktop 2.2.0.4
docker-commpose 1.25.4 ※

Django + Nginx + MySql で開発環境を作るための情報。Qiita 内に優れた記事があり、その通りやれば動くのだが、何をやっているのかよく分からなかったので調べた。

参考サイト
https://qiita.com/kenkono/items/6221ad12670d1ae8b1dd

※ Docker Desktop for Windows をインストールしたら、同時に docker-compose もインストールされている。

まず Windows 側での作業ディレクトリの準備

概要

c:\Local 以下にこういうディレクトリ構造を作成。名前は django とした。

c:\Local
django
├── docker-compose.yml
├── mysql
├── sql
├── nginx
│   ├── conf
│   │   └── app_nginx.conf
│   └── uwsgi_params
└── python
    ├── Dockerfile
    └── requirements.txt
ディレクトリ名 内容 格納するファイル
django 作業用フォルダ docker-compose.ymlを格納
django\mysql MySQL データ 初期は空
django\nginx Nginx 設定用ファイル uwsgi_params を格納 綴りに注意
django\nginx\conf Nginx 設定用ファイル app_nginx.conf を格納
django\nginx\log Nginx ログ 初期は空 自分で追加
django\python dockerfile と requirements.txt を格納
django\sql MySQL 初期化ファイル init.sql
django\src django のソース 初期は空
django\static Web の静的ページ用 あとで入れる

準備するファイル

uwsgi_params

wsgi(Web Server Gateway Interface)は、Python で Web サーバーと Web アプリケーションをつなぐインターフェース。古い技術だと CGI にあたるもの。uwsgi_params は Nginx の wsgi 設定用のファイル。特に書き換える必要がないとされていて、ネット上でも「こう書いておけばいいのだ」とスルーされている。

uwsgi_params
uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

app_nginx.conf

Nginx のメインの設定ファイル。要変更点は特になし。
upstream で、django のサーバーを指定する。サーバーはドメイン名か IP アドレスとオプションでポートを指定する。/static には静的コンテンツを入れるが、url を変える場合は /web という部分を書きかえる。location 以降の記述によって、nginx にアクセスのあった static を除くすべての情報が Django 側へ行く。server_tokens off; はエラーページに nginx のバージョンを非表示にする。

app_nginx.conf
upstream django {
    ip_hash;
    server python:8001;
}

server {
    listen      8000;
    server_name 127.0.0.1;
    charset     utf-8;

    location /web {
        alias /static;
    }

    location / {
        uwsgi_pass  django;
        include     /etc/nginx/uwsgi_params;
    }
}

server_tokens off;

init.sql

要変更点はデータベース名
docker の MySQL image は /docker-entrypoint-initdb.d/ にあるスクリプトで、最初に image を起動したときの初期化が行える。後に django を実行する際に DB 作成を許可するデータベース名は必要に応じ変更。

init.sql
GRANT ALL PRIVILEGES ON test_todoList.* TO 'user'@'%';

FLUSH PRIVILEGES;

requirements.txt

要変更点はバージョン指定。バージョンを省略すると最新版が入るが、バージョン合わせは結構大変なので、そのまま使っておく。このバージョンは 2019/05 頃の最新のもの。
pip で指定のパッケージを指定のバージョンで一括インストールすることができる。

requirements.txt
Django==2.0.4
uwsgi==2.0.17
PyMySQL==0.8.0

dockerfile

要変更点は、python のバージョン(元は 3.6)。
ENV PYTHONUNBUFFERED 1は、バッファがたまってから出力するのを避ける指定。RUN 命令は既存イメージ上でコマンドを実行し、その結果得られたイメージは Dockerfile の次のステップで使われる。WORKDIR 命令は Dockerfile で次の行の ADD の実行時の作業ディレクトリの指定。もし WORKDIR が存在しなければディレクトリを作成する。

dockerfile
FROM python:3.6
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/

docker-compose.yml

docker-compose の本体の設定ファイル。YAML ファイルのインデントはスペース 2 個単位で行わないと、エラーが出ることに注意。

Nginx 記述部

要変更点は、イメージのバージョン(元は 1.13)、ポート番号(8000)。volume はファイルの配置で、Windowsのパス:コンテナ内のパス。

db 記述部

要変更点は、MySql のバージョン(元は 5.7)、データベース名、ユーザー名、パスワード名、ログ出力先。ボリュームは必要に応じ変更。データは、Windows 側の mysql フォルダと同期して永続化する。command は MySQL の文字コードの設定で、デフォルトの latin1 から utf-8 に変える。

python 記述部

要変更点は django のプロジェクトの名前。
command は uwsgi を使用してポート 8001 を開放。app.wsgi の app は Django のプロジェクト名で、django-admin startproject app の app部分。--py-autoreload 1 は Django アプリ開発の際に、ファイル等に変更があった際は自動リロードする。--logto /tmp/mylog.log はログを残す指定。

docker-compose.yml のファイル全体

正常に立ち上がるまでは、ユーザー名などは下記に記載のままやる方が、トラブルが少なく得策。

docker-compose.yml
version: '3'

services:
  nginx:
      image: nginx:1.13
      ports:
        - "8000:8000"
      volumes:
        - ./nginx/conf:/etc/nginx/conf.d
        - ./nginx/uwsgi_params:/etc/nginx/uwsgi_params
        - ./static:/static
      depends_on:
        - python

  db:
      image: mysql:5.7
      command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
      ports:
        - "3306:3306"
      environment:
        MYSQL_ROOT_PASSWORD: root
        MYSQL_DATABASE: todoList
        MYSQL_USER: user
        MYSQL_PASSWORD: password
        TZ: 'Asia/Tokyo'
      volumes:
        - ./mysql:/var/lib/mysql
        - ./sql:/docker-entrypoint-initdb.d

  python:
      build: ./python
      command: uwsgi --socket :8001 --module app.wsgi --py-autoreload 1 --logto /tmp/mylog.log
      volumes:
        - ./src:/code
        - ./static:/static
      expose:
        - "8001"
      depends_on:
        - db

イメージのダウンロードとコンテナ作成、設定

ここまでの時点で作成した django フォルダのバックアップを取っておくと、このあと各イメージのバージョンが合わないなどの不具合があったときに、やり直しが早く済む。

インストールと docker-compose の実行

まずは django のプロジェクトは置かない状態で下記のように実行し、app という名前の新規プロジェクトを作成する。ダウンロードとインストールが進む間、変なエラーが出ていないかを見続けておく方がいい。

docker-compose run python django-admin.py startproject app .

データベースの切り替え

エラーが出なかったら、次にデータベースをデフォルトの sqlite から MySQL に切り替える。\django\src\app 内の stttings.py に記載を追加する。import os のあとに、以下の行を追加する。(import os は 2 行は要らないので念のため)

settings.py
import os
import pymysql

# connect mysql
pymysql.install_as_MySQLdb()

同ファイルにはデータベースの指定をする記述があるので、それを以下の記述に置き換える。要変更点は、データベース名、名前、ユーザー、パスワード。だが正常に立ち上がるまでは、とりあえずこの設定のまま動かした方が確実。

settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'todoList',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'db',
        'PORT': '3306',
    }
}

マイグレーション

データベースの変更を django に知らせて反映させる。データベースのバージョンが合わなかったりすると、この時点でエラーが出る。

docker-compose run python ./manage.py makemigrations
docker-compose run python ./manage.py migrate

管理者の設定

django の管理者のユーザー名とパスワードを設定する。ユーザー名はデフォルトで root となっている。まずは捨てパスでいいと思うが、あまりいい加減なパスワード(password など)を入力するとダメと言われる。

docker-compose run python ./manage.py createsuperuser

コンテナの起動

docker-compose up -d

ブラウザで http://localhost:8000 にアクセスして Django のページが見えたら完成。停止は docker stop $(docker ps -a -q)で、起動はdocker-compose up -dで。

作成したソースの反映

新しいアプリを置き django の設定を更新

開発したアプリ(ここでは memo とする)をプロジェクトに入れる。フォルダ memo ごと src 下に置く。

settings.py の INSTALLED_APPS に'memo.apps.MemoConfig'を追加

src\app\settings.py
INSTALLED_APPS = [
    'memo.apps.MemoConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

app\urls.py にfrom django.urls import includeと、 url へのパスpath('memo/', include('memo.urls'))を追加

src\app\urls.py
from django.urls import include

urlpatterns = [
    path('memo/', include('memo.urls')),
    path('admin/', admin.site.urls),
]

変更をマイグレーションして django に認識させる

docker-compose run python ./manage.py makemigrations
docker-compose run python ./manage.py migrate
docker-compose up -d

これでブラウザからhttp://localhost:8000/webで \static に置いた静的な html ファイルが見える。http://localhost:8000/memoで、memo アプリケーションが見える。

おわり

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む