20200803のMySQLに関する記事は5件です。

『失敗から学ぶRDBの正しい歩き方』を読んでいく(後編)

前編は こちら

概要

11. 見られないエラーログ

アンチパターン

  • エラーログの軽視と無知。
    • 大きな問題を未然に防ぐチャンスを自ら潰している。
  • エラーログの運用設計をシステムの設計時に行っていない。
  • エラーログの吐き出し過ぎ。
    • 担当者が見なくなる大きな要因の一つ。

エラーログ出力の設計

  • 運用ログとして欲しい情報。

    • いつ(タイムスタンプ)
    • だれが(ユーザー)
    • どこに(データベース)
  • 監査ログとして欲しい情報。

    • どこから(クライアントのIPなど)
    • 何をしたか(実行されたSQLコマンド)
    • どうなったか(エラーコード、エラーメッセージ)

エラーログの監視

PostgreSQLの場合

  • 重要な通知を知るべきすべての人に素早く・正しく・漏れなく通知できること
    • Slackへの通知にはサーバ監視サービスのMackerelやサーバ監視ツールのZabbixなどを使い、「PANIC」などの文字列が出力された場合にアラートとして扱う仕組みが一般的。
深刻度 本番環境でのロギング 通知
DEBUG1~DEBUG5 場合による(デバッグで必要などの理由がなければ本番では行わず、ステージングのみで行う) しない
INFO 場合による(統計情報で取得できない場合など他で代替できないときのみ) しない
NOTICE する しない
WARNING する しない
ERROR する Slackの、エラー対応のためのチャンネル(errorチャンネルなど)に通知
FATAL する Slackの主要チャンネル(generalなど)に通知(@channel付き)
PANIC する Slackの主要チャンネル(generalなど)に通知(@channel付き)

まとめ

  • エラーログの種類について知り、適切な設計・運用を行う。

ログを見やすくする工夫

Elastic Stackを活用する
  • ログの集計結果をHTMLやCLI上でわかりやすく表示してくれるため、私達を大いに助けてくれるツール。
    • Logstashでログを集約、Elasticsearchで集計、Kibanaで可視化。
PostgreSQLの場合
  • PANICになってからでは、障害が発生しているため対応しとしては出遅れているので、ログレベルLOGのエラーログを集計して事前に問題を検知し、より早い初動で対応する。
MySQLの場合
  • Error, Waring, Note のうち、 Note 以外を監視する。
    • Elastic Stackの活用やホワイトリスト形式の文字列監視も良いプラクティス。

12. 監視されないデータベース

アンチパターン

  • RDBMS、ミドルウェアの監視(モニタリング)をする文化が存在しない。

ミドルウェアの監視の種類

1. サービス(プロセス)の死活監視

  • 「いち早く障害発生を確認できるようにする」ために必要な監視。

2. 特定条件のチェック監視

  • 「特定の条件を設けて、障害を未然に防いだり、復旧にいち早く取り掛かれたりするようにする」ために必要な監視。
    • 例)ディスク容量が90%になるとアラートが飛ぶ。

3. 時系列データをもとにしたメトリックス監視

  • 「状況の変化を時系列で管理することで、キャパシティプランニングや障害の予兆の把握に役立てる」ために必要な監視。

モニタリングの対象と実践

  • メトリックを見て、シナリオを考えることが大切。

OS側

  • ディスクI/O
  • ネットワークトラフィック
  • CPU利用率
  • メモリ利用率

RDBMS側

  • SELECT/INSERT/UPDATE/DELETEなどのSQLの実行量
  • 実際に読み込まれているレコードの量
  • インデックスヒット率
  • デッドロックの可否
  • テンポラリファイルの作成の有無
  • ロックの量と時間

MySQLのモニタリングツール

PMP
  • ZabbixやCactiのプラグインとして公開されており、手軽に使うことができる。
    • MySQLの項目をかなり細かく取ることができる。

PostgreSQLのモニタリングツール

pg_monz
  • Zabbixのプラグインとして使うことができる。

まとめ

  • モニタリングを続け、育てることが大切。
    • モニタリングはインフラの見える化。
      • プログラミングに対するテストコードと同じ。
    • パフォーマンスのモニタリングを、インフラエンジニアとアプリケーションエンジニアが一緒に、1~2週間に1回は行うようにする。
  • モニタリング後のチューニングが大事
    • プログラミングに対するリファクタリングと同じ。

12-2. ミドルウェアの監視の種類

コラム 可視化と改善は両輪

13. 知らないロック

アンチパターン

  • 意図せずロックがかかり問題が発生する。
    • ロックの粒度や性質を知らない。
    • DBの負荷同様にロックをモニタリングの対象にしていない。

ロックの基本

デッドロック

  • 「複数のトランザクションが、もう一方の処理が終わるのをお互い待って身動きが取れなくなっている状態」
    • デッドロックが発生しないように、ロックでは取得の順番が大切。
MySQLのギャップロック
  • 対象が存在しなくてもロックを取る
    • 「INDEX値を持つ行」と「INDEX値を持つ行」の間にあるギャップ
    • 先頭の「INDEX値を持つ行」の前に存在するギャップ
    • 末尾の「INDEX値を持つ行」の後に存在するギャップ
MySQLのネクストキーロック
  • 対象よりも1つ先の行までロックを取る。

明示的ロック

  • 自ら宣言して取得するロック。
    • 例)外部キー制約を利用した状態で子テーブルに対する更新を行った場合は親テーブルがわに共有ロックを取得する。

まとめ

  • RDBMSごとのロックの振る舞いを知っておく。
    • 時にはクリティカルなバグをうみ、最悪サービスが停止することもある。
      • ロックの振る舞いについてはドキュメントを読み、手を実際に動かし、正しい知識を身につける。

14. ロックの功罪

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

15. 簡単過ぎる不整合

15.2 非正規化の誘惑

コラム 非正規化と履歴データの違い

16. キャッシュ中毒

キャッシュについて知る

17. 複雑なクエリ

17-2. 複雑なクエリの発端

18. ノーチェンジ・コンフィグ

18-2. コンフィグを知る

19. 塩漬けのバージョン

19-2. なぜバージョンアップは重要なのか

20. フレームワーク依存症

20-2. フレームワークが生むメリットとデメリット

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

【Laravel】MySQL設定メモ

MySQLにデータベースを作成する

ターミナル
$ mysql -u root  

mysql > CREATE DATABASE アプリケーション名;

laravelファイルの.envを修正する 

.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=[アプリケーション名]
DB_USERNAME=root
DB_PASSWORD=
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FuelPHPにおいてtimestampで範囲を指定して取得するとき注意点

概要

created_atupdated_at などに使われる timestamp 型は非常に便利で、不等号で簡単に比較ができるのですが、気を付けないとうまく動いてくれません。すごく基本的なことですが、場合によっては適当に書いても正常に動いてしまうことがあるので意外と気づきにくい部分だと思います。

本題

デフォルトの unixtime で扱っている場合
e.g.)1596447140 など
はそのまま使えて、

unixtime.php
$query = \DB::select()
->from('table_name')
->where('created_at', '>', strtotime('-1 week'))
->execute();

のように書くだけで比較ができます。この場合は1週間前よりあとに作られたレコードだけ取得します。

一方、違うフォーマットで扱っている場合
e.g.)2020-08-03 18:32:20 など
は注意が必要で、フォーマットも合わせてあげる必要があります。例の場合は、

anyformat.php
$query = \DB::select()
->from('table_name')
->where('created_at', '>', date('Y-m-d h:i:s', strtotime('-1 week')))
->execute();

と書くと同様の動きをしてくれます。

まとめ

しっかり使えば非常に便利なtimestamp。一つのサービスで使うtimestampのフォーマットは合わせた方が良いですね。
余談ですが、'Y-m-d h:i:s'と書くべきところを'Y-m-s h:i:s'と書いていて、更新するたびに取得されるレコードが違うということになったりもしました。さすがに気づきましたけど(30分ほど苦戦して上司に聞いて)。

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

AmazonRDSで外部接続できるMysql環境構築

AmasonRDSにMysql環境を構築(無料利用枠)してみました。
あと、はまった内容も載せています。

こんな人にはいいかも?
・自分のパソコンにインストールしたくない。
・パソコンが壊れた場合、リカバリ作業をしたくない。
・別のパソコンと共有したい。
・お金を使いたくない。
・大容量じゃなくても大丈夫。
・一時的(1年以内)な利用で大丈夫。

忙しい方は、以下の項をどうぞ。
・3.セキュリティグループの作成
・7.パラメータグループの作成
・9.再度データベースの作成

参考

[AWS]RDSにて外部サーバーからの接続を許可する

手順

1.データベースの作成

「Amazon RDS」→「データベース」→「データベースの作成」
image.png

2.データベースの作成

赤枠の所を変更していきます。
image.png
image.png
image.png
image.png
image.png
最後に「データベースの作成」


image.png
「ステータス」が「利用可能」になるまで待ちます・・。5~10分位だった気がします。

3.セキュリティグループの作成

「amazon EC2」→「セキュリティグループ」
image.png
「セキュリティグループの作成」を選択


image.png
「セキュリティグループ名」「説明」を入力。(何でもよい)
「インバウンドルール」に「ルールを追加」で、ポートを「3306」、アクセス許可するIPアドレスを指定します。


image.png
最後に「セキュリティグループの作成」

4.セキュリティグループの適用

「Amazon RDS」→「データベース」
image.png

対象のデータベースを選択して、「変更」


image.png
「セキュリティグループ」に先ほど作成した内容を選択します。


image.png
「すぐに適用」、「DBインスタンスの変更」

5.接続確認

「A5SQL」で接続確認します。
image.png

・「ホスト名」は、エンドポイント
・ユーザID、パスワードは「1.データベースの作成」より。

エンドポイント

「amazonRDS」→「データベース」→作成したデータベースのリンクをクリック
image.png

パスワードを忘れた場合

上記の「4.セキュリティグループの適用」の手順を行い、
「セキュリティグループ」ではなく、「新しいマスターパスワード」を設定してください。
image.png

image.png
接続できなければ、再度、1~4の手順をやり直してみてください。。

6.Mysqlの設定(大文字・小文字区別)

テーブルを作成して、クエリを実行してみる。

select COUNT(*) from USER_MST

こんなエラーが表示される。。

#42S02Table 'xxxxxx.USER_MST' doesn't exist

「USER_MST」というテーブルが無い・・・?

image.png

A5SQLを見てもあるんだけど・・。

テーブル名を小文字にすると、問題無し。。

select COUNT(*) from user_mst

原因は、「大文字・小文字」の区別が有効になっているからの模様。
以下、公式より。
9.2.2 識別子の大文字と小文字の区別

7.パラメータグループの作成

通常であれば「my.cnf (linux) / my.ini (windows) 」の値を書き換えればよいのですが、
amazonRDSの場合は、「パラメータグループ」の書き換えになります。


「amazonRDS」→「パラメータグループ」
image.png

「パラメータグループの作成」


image.png
「パラメータグループファミリー」→「mysql8.0」
「グループ名」「説明」に入力(なんでもよい)

最後に「作成」


image.png
出来上がったパラメータを選択


image.png
「lower_case_table_names」で絞り込んで、パラメータの値を「1」にする。
最後の「変更の保存」

8.DBパラメータグループの適用

上記「4.セキュリティグループの適用」の手順を行い、
「セキュリティグループ」ではなく、「DBパラメータグループ」を作成した内容に変更。
image.png


で、ここではまる。。。

image.png
「すぐに適用」、「DBインスタンスの変更」をしようとすると・・・

The parameter value for lower_case_table_names can't be changed for MySQL 8.0 DB instances

ググってヒットした記事↓
Amazon RDS における MySQL の既知の問題と制限

「Amazon RDS DB インスタンスに使用する MySQL のパラメータの例外」の項を読んでも問題なさそうだけど・・。

再起動してみよう!

変更を破棄して、「停止」→「再起動」

Can only reboot db instances with state in: available, storage-optimization, incompatible-credentials, incompatible-parameters. Instance database has state: stopping

「停止」後、起動できなくなる。。。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/rds-incompatible-parameters/
https://qiita.com/matsumoto_sp/items/4808576159c92f8916f5

「リセット」かサポート問い合わせ・・?
めんどくさそう。。

9.再度データベースの作成

データベースを最初から作りました。

※Mysqlのバージョンがたまたま悪かったのかと思い、「8.0.20」にしています。
 赤枠がデフォルトからの変更点です。

image.png
image.png
image.png
image.png
image.png

※「3.セキュリティグループの作成」「7.パラメータグループの作成 」で
既に「セキュリティグループ」と「パラメータグループ」を作成済みなので、他に操作は必要ありません。

10.再度クエリの実行

image.png

うまくいった!

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

dockerでMySQLのサンプルデータベースのSakilaを使用した環境をすぐ使用できるように設定してみた

私はdocker初心者です。間違いやもっと良い方法があれば教えていただけるとありがたいです。


SakilaとはMySQLが公式で用意しているサンプルデータベースです。

https://dev.mysql.com/doc/sakila/en/

こちらからダウンロードできます

https://dev.mysql.com/doc/index-other.html

DVDレンタル情報が保存されているデータベースで、個人的にはMySQLのデータを使って試したいときに使うというのが便利だと思います。

それをdockerでちょちょっと環境が作成できるようにやってみました。


参考

Dockerfile作成

mysqlの公式イメージを使ってDockerfileを設定してみました

Dockerfile
FROM mysql:8

ENV MYSQL_ROOT_PASSWORD=root

RUN apt-get update \
    && apt-get install -y wget unzip \
    && wget http://downloads.mysql.com/docs/sakila-db.zip \
    && unzip sakila-db.zip \
    # docker-entrypoint-initdb.d/ の .sql ファイルが自動でアルファベット順に実行されるので、リネームしつつ移動
    && mv sakila-db/sakila-schema.sql /docker-entrypoint-initdb.d/01_sakila-schema.sql \
    && mv sakila-db/sakila-data.sql /docker-entrypoint-initdb.d/02_sakila-data.sql

Dockerfileをビルドしてコンテナ作成

$ docker build -t sample .
(省略)
$ docker run --name sakila -d sample
(省略)
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                 NAMES
a599ee328437        sample              "docker-entrypoint.s…"   About a minute ago   Up About a minute   3306/tcp, 33060/tcp   sakila

mysqlに接続しshow tables;を実行

$ docker container exec -it sakila mysql -uroot -proot -Dsakila
mysql: [Warning] Using a password on the command line interface can be insecure.
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.21 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 tables;
+----------------------------+
| Tables_in_sakila           |
+----------------------------+
| actor                      |
| actor_info                 |
| address                    |
| category                   |
| city                       |
| country                    |
| customer                   |
| customer_list              |
| film                       |
| film_actor                 |
| film_category              |
| film_list                  |
| film_text                  |
| inventory                  |
| language                   |
| nicer_but_slower_film_list |
| payment                    |
| rental                     |
| sales_by_film_category     |
| sales_by_store             |
| staff                      |
| staff_list                 |
| store                      |
+----------------------------+
23 rows in set (0.00 sec)

mysql> 

Sakilaのサンプルのdbが作成されていることを確認できました

phpmyadminでも見れるようにしてみた

先ほどのDockerfileと同じディレクトリにdocker-compose.ymlを作成

docker-compose.yml
version: "3"

services:
    db:
        build: .
        container_name: mysql

    phpmyadmin:
        container_name: phpmyadmin
        image: phpmyadmin/phpmyadmin
        environment:
            - PMA_ARBITRARY=1
            - PMA_HOST=mysql
            - PMA_USER=root
            - PMA_PASSWORD=root
        ports:
            - 8080:80
$ docker-compose up -d

http://localhost:8080/

Screen Shot 2020-08-03 at 0.59.40.png

以上です。

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