ハックライフノート

技術的な話とか、覚え書き

[MySQL]replicate-***-dbオプションの罠

皆さん、今日もバリバリMySQLサーバーを駆使していますか?

会社で使用しているのであれば、負荷分散の為にレプリケーションサーバーを用意しているかもしれません。

私の会社も多数のレプリケーションサーバーを稼働させていますが、ついこの前my.cnfにこんな記載をしたんですよね。

replicate-ignore-db =schema_hoge

まあ、このサーバーには特定のスキーマレプリケーションする必要が無かったので、この設定を加えました。

因みにreplicate-ignore-dbオプションは、ざっくり言うとマスターから流れてくるSQLの中で「このスキーマの更新は実行しません」ってオプションです。

こうする事で、レプリケーションさせたくないスキーマやテーブル(replicate-do-db)を指定できるんですね。


ただ・・・この設定を加えてから6時間後、悲劇は起きました。


この設定を加えたサーバーで次々と、UPDATEやDELETEのSQLでエラーが多発し、結局はマスターサーバーからダンプを取り復旧。

replicate-ignore-dbのオプションは消しました。

何が起きたかと言うと、実はこのオプション、マスターサーバーのbinlog_formatで何を指定するかで動作が変わります。

この事はMySQLのリファレンスにも書いており、

ステートメントベースのレプリケーション デフォルトデータベース (つまり、USE で選択されたもの) が db_name であるステートメントを複製しないようにスレーブ SQL スレッドに指示します。

行ベースのレプリケーション データベース db_name 内のテーブルを更新しないようにスレーブ SQL スレッドに指示します。デフォルトデータベースは影響しません。

要するに、マスターサーバーのbinlog_formatでstatementやmixedを指定していた場合、replicate-***-dbオプションは期待通りに動作しません

これらの設定をしていた場合、replicate-***-dbはUSEで指定されたスキーマを基準に判断をします。

なので、例えばバッチ等でデフォルトスキーマをhoge1というスキーマに設定していたとしましょう。

レプリケーション側ではreplicate-ignore-db=hoge2と設定し、マスターサーバーからhoge2スキーマの更新を受け取りません。

しかし、マスターサーバー側で実行されるバッチのデフォルトスキーマはhoge1なので、発行されるSQLは、

USE hoge1;

が頭に付きます。

この状態でhoge2スキーマを明示的に指定したUPDATE文が流れると・・・

USE hoge1;
UPDATE hoge2.hoge2_table ...

はい、これでレプリケーションサーバーを壊すSQLの完成です。

binlog_formatがstatement若しくはmixedの場合、USEで指定されたスキーマを基準に考えるので、replicate-ignore-db=hoge2は虚しくもこのSQLを実行するSQLと判断し、もしhoge2スキーマがスレーブ側に無かったらエラーを起こします。

じゃあどうすんのさ!って話ですが、ちゃんと対策はできるみたいです。

replicate-wild-ignore-table=hoge2.%

といった感じでreplicate-wild-ignore-tableを使用すればいいみたいで、実際テスト環境で試した所無事に更新をブロックできました。

もっとちゃんとリファレンスを読むべきだなぁ・・・

[MySQL]データベースのバックアップとインポート(mysqldump)

基本的な内容ですが、MySQLではデータベースをまるごとバックアップできるコマンドが用意されています。

MySQLをインストールしたディレクトリ(basedir)のbinディレクトリの中に、mysqldumpというコマンドが存在します。

このコマンドを使用すれば簡単お手軽にまるっとデータベースをバックアップ可能に。

下環境はCentOS7、MySQL5.5or5.7で確認しています。

まず基本のコマンド。

/var/lib/mysql/bin/mysqldump -uroot -p --all-databases > dump.sql

引数ですが、-uでユーザー指定、-pでパスワードあり、--all-databasesで全てのDBをdumpになります。

まあ-uと-pは普段のmysqlコマンドでも使いますので、見慣れてるかと。

--all-databasesは存在する全てのDBのバックアップを作成しますので、mysqlスキーマもバックアップされる事にだけ注意。

例えばレプリケーションを張るためにdumpを取った、という用途ではmysqlスキーマはインポートさせないほうがいいかと。

mysqlスキーマの中にはユーザー情報とかも入っているので、環境によって個別に作成するのが吉と見ています。

もし個別のスキーマを指定する場合は。

/var/lib/mysql/bin/mysqldump -uroot -p [database_name] ([table_name]) > dump.sql

この場合1つのスキーマ指定になります、続けて後ろに引数を書くとそれはテーブルの指定になります。

/var/lib/mysql/bin/mysqldump -uroot -p --databases [database_name1] ([database_name2]...) > dump.sql

複数のスキーマをdumpする場合、--databasesオプションを指定することで、その後に書いたものは全てスキーマ名と認識されます。

あと、よくあるのがdumpしたファイルをインポートすると文字化けする!って現象が起こりますが、--default-character-set=[文字セット]を指定することで解消されます。

UTF-8で全てのDBをdumpだったら、こんな感じですね。

/var/lib/mysql/bin/mysqldump -uroot -p --default-character-set=utf8 --all-databases > dump.sql

これぐらいを覚えておけば大抵は事足りますが、細かいオプションも結構あるので他は公式のリファレンスを参照して下さい。

MySQL :: MySQL 5.5 Reference Manual :: 4.5.4 mysqldump — A Database Backup Program
MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.5.4 mysqldump — データベースバックアッププログラム

逆にインポートは簡単です。

/var/lib/mysql/bin/mysql -uroot -p < dump.sql

基本はこれですが、先述した--default-character-setオプションを付けた場合はこちらでも指定する必要があります、多分。

/var/lib/mysql/bin/mysql -uroot -p --default-character-set=utf8 < dump.sql

これであなたもmysqldumpマスターに、バンバンdumpを取ってサーバーのCPUとディスクに多大なる負荷をかけてあげましょう。

[C#]staticなメソッドやフィールドをクラス名を省略して記述する

インスタンス化しなくても使えるようになる静的な宣言staticですが、通常であればusingディレクティブにはクラス名まで書けません。

ですが

using static MyApplication.Directory.Classname;

usingディレクティブの後にstaticと書いてあげれば、あら不思議、staticなメソッドもフィールドもスマートに書けちゃいます。

ほぼ一発ネタみたいなものですが、覚えておくと便利です。

因みに、usingディレクティブでは別名を付けることも可能です。

using A = MyApplication.Directory.Classname;

こうすれば、Classname内のメソッド等がA.でアクセスできます。

[MySQL]SELECT文で複数のカラムを複数の条件で指定する

タイトルだとちょっと分かりにくいですが、こんな事できるんだって少し驚いたのでそのメモです。

通常SELECT文と言えばこんなクエリになります。

SELECT * FROM hoge_table
WHERE column1 = 'cons'

んで、一つのカラムに対して複数条件はこれ。

SELECT * FROM hoge_table
WHERE column1 IN ('cons','sols')

ここまではまだ普通なんですが、複数のカラムに対して更に複数の条件を叩きつけたいって時が稀に起こるんですが、それが以下のSQLで可能です。

SELECT * FROM hoge_table
WHERE (column1,column2)
IN (('one','two'),('three','four'))

こうする事で、column1とcolumn2の組み合わせがone,twoまたはthree,fourの条件で検索できます。

奥が深いですね。

[RaspberryPi]RaspberryPi 3 B+にCentOS7をインストール

つい最近まではRaspberryPi B+という初代のものしか持っていなかったのですが、会社の人と話している内に最新のものが欲しくなったので買ってしまいました。

以下RaspberryPi 3 B+と書くのはめんどいので、RasPiと略します。

先月のPayPay20%還元祭りでi9 9900Kとマザボ+メモリを買った際、ポイントが23000円程度付いたので、PayPayが使用できるTSUKUMOにてRasPi本体+RasPi用電源+専用ケース+SDカード64GBの一式を買って、早速セットアップしました。

最新のRasPiを買ったのにはもう一つ理由がありまして、RasPi2or3だとCentOSが使用できるんですよね。

普段会社のサーバーではCentOSを使用しているので、DebianベースのRasbianよりもコマンド操作的な意味で慣れているので、これを使いたかったんですよ。

1.RasPi用のCentOSイメージのDL&書き込み

http://isoredirect.centos.org/altarch/7/isos/armhfp/

RasPi用のCentOSは上記のリンク先で入手できます。

記事執筆時点ではCentOS-Userland-7-armv7hl-generic-Minimal-1810-sda.raw.xzが最新かつCUIのみのインストールメディアなので、これをDLして7zip等で解凍します。

したらrawファイルが生まれますので、これをDD for WindowsでSDカードに書き込みをします。

そこそこの時間がかかりますので、お茶でも飲んで待ちましょう。

書き込みが終了したら、いよいよ起動に入ります。

2.CentOSの起動

本体にHDMIケーブルとキーボードを最低限取り付け、電源を差し込みます。

RasPiは電源スイッチが無く、電源を挿したらそのまま起動します。

起動後、ログイン画面になったらuser:root、pass:centosでログインします。

3.パーティションの拡張

# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       2.0G  762M  1.1G  42% /
devtmpfs        459M     0  459M   0% /dev
tmpfs           463M     0  463M   0% /dev/shm
tmpfs           463M   12M  451M   3% /run
tmpfs           463M     0  463M   0% /sys/fs/cgroup
/dev/mmcblk0p1  500M   43M  457M   9% /boot
tmpfs            93M     0   93M   0% /run/user/0

初期状態だと、パーティションが2GB程度しかroot(/)に割り当てられてないので、rootfs-expandコマンドを実行しましょう。

# rootfs-expand

これだけでSDカードの容量をフルに使用してくるようになります、便利!

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root        58G  762M   56G   2% /
devtmpfs        459M     0  459M   0% /dev
tmpfs           463M     0  463M   0% /dev/shm
tmpfs           463M   12M  451M   3% /run
tmpfs           463M     0  463M   0% /sys/fs/cgroup
/dev/mmcblk0p1  500M   43M  457M   9% /boot
tmpfs            93M     0   93M   0% /run/user/0

4.日本語環境に設定する
英語環境のままでも問題は無いですが、場合によっては日本語の方がいいので変更します。
CentOS7はlocalectlコマンドで言語設定を行います。

# localectl status

で現在の言語設定を見る事ができます。
日本語環境にするには、以下のコマンドを発行。

# localectl set-locale ja_JP.utf8

まあ見たまんまですね、言語は日本語で文字セットはUTF-8を使用します。Shift-JIS滅びてくれ

後は必要な設定を各自で行う形です。
今の所セットアップしただけで、特に使い道は決まってないのでいずれか何か思いついたら何かしらをやってみようと思います。

[サーバー]TRPGオンセ用ツール"どどんとふ"のサービスを立ち上げました

前回の記事に関連した話ですが、自鯖どどんとふのサービスを導入してみました。

どどんとふというのは、ブラウザ上で動作するTRPGのオンセをするにあたって必要な機能を一通り揃えたサービスになります。

webサーバー自体はずっと稼働していたんですが、何も無かったので流石に寂しく思い、あとは私自身がよくCoCTRPGをプレイするのでどうせならと入れてみました。

まあ、毎回GMなんですけどね。

どどんとふはソースが公開されているので、誰でも導入する事ができるのでやってみた感じです。

今の所まだ全然利用されてませんが、逆に言えばそれだけ快適なはずなので、是非利用して下さい。

サーバー↓
trpg.alterzero.net

[Apache]Let's EncryptでSSL対応化した話(ワイルドカード使用)

ずっとやろうと思っていたけどやらなかった、自鯖で運用しているwebサーバーのSSL対応についてです。

SSLってなんぞやって話については調べれば腐るほど情報がありますが、一言で言えば安全性を高める技術ってことです。

サイトをリクエストしたクライアントPCとサーバー間の通信をセキュアにしてくれるので、今の時代はまず導入しているのが一般的になりつつあります。

将来的にはSSL対応していないサイトは表示すらできなくなる可能性もあります。

そうなったら面倒なので、重い腰をあげて取り掛かりました。


で、SSL対応をするには証明書の発行が必要で、無料や有料のものもピンキリであるんですが、有料のものは大体個人で扱うような価格設定ではないケースが多いので、今回は無料で発行できるLet's Encryptを利用して証明書の発行を行いました。

まあ、webサーバー自体放置状態なので・・・


証明書の発行はサーバーで行いますが、Let's Encryptの場合certbotという自動で証明書を発行してくれるクライアントソフトがあるので、それを落とします。

yum install epel-release

epelレポジトリをインストールしていない場合は、まずepelレポジトリを導入します。

yum install certbot python-certbot-apache

で、certbot本体をインストール。

次にcertbotを利用して証明書の発行をするんですが、自分の環境では複数のサブドメインを運用しているのでそれ用のコマンドを引数として与えてやります。

sudo certbot certonly --manual --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory -d alterzero.net -d *.alterzero.net

長いですが、こんな感じでコマンドを実行するとcertbotが走り対話形式で設定を聞いてきます。

alterzero.netの部分はご自身の環境に合わせて下さい、ちなみにこのドメインは私が趣味で取得したドメインですが今の所何もコンテンツがありません。

これを機に色々と立ち上げてみるつもりですが・・・

話が逸れましたが、対話形式では基本的に英語の内容を読んでyes or noを答えて下さい。

ただし、途中でDNSにTXTレコードを追加しろと言ってくるので、大人しくドメイン管理サービスでTXTレコードを設定します。

_acme-challengeをサブドメインとし、レコードの種類をTXT、valueについては表示されている暗号みたいな文字列をそのままぺっと貼っつけて下さい。

その後、追加したTXTレコードがドメインに追加されているかをチェックします。

nslookup -q=txt _acme-challenge.alterzero.net

とでも投げれば、最初は見つからないと言われますが数分も経てば追加したTXTレコードのvalueが流れてきます。

ここでも当然ご自身のドメインを指定して下さい。

後はさっきの途中で止めているcertbotでEnterを押して続けて下さい。

Conguratulation!と出ていれば、証明書の発行は終わりです。

/etc/letsencrypt/live/(ドメイン名)/のディレクトリ以下に各証明書と秘密鍵が生成されているので、そちらを使用しましょう。

cert.pem = サーバー証明書
privkey.pem = 秘密鍵
chain.pem = 中間証明書

Apacheへの環境設定は多分各個人でバラバラなので、次回あたりにでも私の環境での導入を書いておこうと思います。