2015年8月4日火曜日

mysqldumpじゃないよ、mysqlpumpだよ in MySQL 5.7.8 (新機能編)

TL;DR

MySQL 5.7.8には、mysqlpumpなるmysqldumpの後継バックアップクライアントが同梱されている。インデックスの遅延ロードや進捗の出力、パラレルでのダンプなど魅力的な拡張機能が入っている。

ただし、mysqlpumpの方は「全テーブルがInnoDB」「master_info_repository= TABLE」「relay_log_info_repository= TABLE」「gtid_mode= ONの場合にはMySQL 5.7.5以降であること(OFFの場合はこの制約は入らない)」「パラレルでバックアップする場合は更新を自分で止めておかなくてはならない」であることを前提に作られているため、それを満たさない場合は mysql40dump のようなラッパーを何かしら作る必要があります(レプリケーションの情報はテーブルに保存されていてそれはダンプに含まれるから、SHOW SLAVE STATUSとかSHOW MASTER STATUSの情報は吐いてくれない)


mysqlpumpだけの機能はこんな感じ。mysqldumpとの機能の違いについては別の記事

* --defer-table-indexes
  * MySQL 5.6における大量データロード時の考慮点 - SH2の日記 で語られているように、ダンプファイルのリストアのようなケースでは 「バルクINSERT時はインデックスをつけない」「INSERTが終わってからALTER TABLEでつける」のが最速になる。これをやってくれる。
  * Percona Serverのmysqldumpに入っている --innodb-optimize-keys と同じような動作。

$ mysqlpump --defer-table-indexes d1 t1
-- Dump created by MySQL dump utility, version: 5.7.8-rc, Linux (x86_64)
-- Dump start time: Wed Jul 15 18:35:46 2015
-- Server version: 5.7.8
..
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `d1` /*!40100 DEFAULT CHARACTER SET latin1 */;
CREATE TABLE `d1`.`t1` (
`num` int(11) NOT NULL,
`val` varchar(32) DEFAULT NULL,
PRIMARY KEY (`num`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
;
INSERT INTO `d1`.`t1` VALUES (1,"one"),(2,"two");
USE `d1`;
ALTER TABLE `d1`.`t1` ADD KEY `val` (`val`);
..

↑では明示的につけてるけど、暗黙のデフォルトON。何も考えなくてもmysqlpumpからのリストアはmysqldumpからのリストアに比べて速くなるはず。すてき。


* --compress-output
  * mysqldumpは必ず平文でSQLが出力されるので、ストリームで圧縮したい時はパイプでつなげてリダイレクトするしかなかったが、これを付けるとmysqlpumpの標準出力そのものが既に圧縮された状態で出てくる。
  * 引数は"zlib"もしくは"lz4"で圧縮形式を指定するぽい。

$ mysqlpump d1 t1 > cleartext.sql
Dump progress: 0/1 tables, 2/2 rows
Dump completed in 410 milliseconds

$ mysqlpump --compress-output=lz4 d1 t1 > lz4.sql
Dump progress: 0/1 tables, 2/2 rows
Dump completed in 374 milliseconds

$ mysqlpump --compress-output=zlib d1 t1 > zlib.sql
Dump progress: 0/1 tables, 2/2 rows
Dump completed in 367 milliseconds

$ ll *.sql
-rw-r--r-- 1 root root 1161 Jul 16 11:32 cleartext.sql
-rw-r--r-- 1 root root  705 Jul 16 11:33 lz4.sql
-rw-r--r-- 1 root root  510 Jul 16 11:33 zlib.sql

( ´-`).oO(.sqlってつけたのは間違いだな我ながら。


* --exclude-*
  * databases, events, routines, tables, triggers, usersをそれぞれ除外指定できる。除外対象を複数指定したい時はコンマ区切りで渡す。すてき。
  * --ignore-tableはテーブル単位でしか指定できないし、データベース名からの完全修飾が必要で、複数テーブル指定する時はオプションから複数指定しないといけなかったのに比べると、かなり柔軟になった。


* --include-*
  * --databasesや--tablesと同じようなアレになるんだろうか。コード読みたい。

* --default-parallelism
  * バックアップの並列度を指定できる。暗黙のデフォルトは2で2スレッドで並列にバックアップを取る。ただし、並列でやると *ダンプファイルの中身が交差するよ* って書いてあって、つまり別々に叩いたSELECTをそれぞれ標準出力に独立して書き出す感じ。
  * この値に1より大きい値を指定した時(つまりパラレルでダンプする時)、START TRANSACTIONはそれぞれのスレッドが別々に叩くので、--single-transactionは意味を持たない。
    * よって、更新トラフィックのある状態で--default-parallelism > 1だとバックアップとしてのデータの整合性は保証されない
    * STOP SLAVEできるバックアップ用のスレーブからパラレルで取るか、STOP SLAVEしたくないなら--default-parallelism = 1 && --single-transactionで取るか(ただしその場合も *今までの* レプリケーション再開に必要そうなSHOW SLAVE STATUSの情報とかは一切取ってくれない、master_info_repository= TABLE && relay_log_info_repository= TABLE && mysql.gtid_executedに異存している。

* --parallel-schemas
  * スキーマ単位でパラレルにダンプを取ってくれる。
  * 数値を渡すとその数でパラレルにダンプ、コンマ区切りのスキーマのリストを渡すと 「そのスキーマだけ特別扱いしてスレッドを起動、リストに記載されてないスキーマは1つのスレッドでダンプ」だそうな。

* --skip-definer
  * VIEWやSTORED PROCEDUREのDEFINER句をかっ飛ばしてくれる。
  * 本番のテーブルからVIEWの定義をダンプしてきたけど、リストア先はmysqlスキーマまでコピーしてないからDEFINERがいないって言われて怒られることがなくなる。
  * "mysqldump definer" とかぐぐると、消すためのワンライナーを紹介してる記事があったりするので、それなりに需要があるんだろうとおもう。

* --users
  * 前にオレオレパッチで対応していた、mysql.userの情報とかをCREATE USER & GRANTのステートメント形式で出力してくれるオプション。--triggersや--eventsと同じ類。
    * MySQLのバージョンアップをmysqldumpでやると面倒なので—grantsをつけてみる | GMOメディア エンジニアブログ

$ mysqlpump --users d1 t1
..
CREATE USER 'yoku0825'@'%' IDENTIFIED WITH 'mysql_native_password' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT USAGE ON *.* TO 'yoku0825'@'%';
CREATE USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
..

おおお、いいね。


* --watch-progress
  * ダンプの進み具合を *標準エラー出力* に吐く。 *暗黙のデフォルトON* 。cronに仕込んで標準エラー出力を拾うようにしていると進捗だけごりごり拾う羽目に遭うので注意。

$ mysqlpump tpcc > test
Dump progress: 0/9 tables, 10/594278 rows
Dump progress: 6/9 tables, 543510/594278 rows
Dump completed in 1525 milliseconds

無効化するには--skip-watch-progressなんだけど、

$ mysqlpump --skip-watch-progress tpcc > test
Dump completed in 1558 milliseconds


:(;゙゚'ω゚'): おいskip-watch-progressしてもDump completedは標準エラー出力に吐くのかよ。。


長くなってきたので取り敢えずここまで。
mysqldumpとの違いについては別のエントリーで。

0 件のコメント :

コメントを投稿