Yakstは、海外の役立つブログ記事などを人力で翻訳して公開するプロジェクトです。
6日前投稿

mysqlpumpユーティリティー

MySQLの論理バックアップ生成ツール「mysqldump」の後継にあたる「mysqlpump」の特徴と使い方についての解説。
原文 The mysqlpump Utility - Percona Database Performance Blog (English)
翻訳者 C17de91fbad737faaa06173533ed323d kakuka4430


この記事では、mysqlpumpコマンドの使い方を見てみようと思います。

mysqlpumpは論理バックアップを取得するツールです(実ファイルではなく、データをSQLとしてバックアップするという意味)。このツールは MySQL5.7.8 で追加され、データベースをダンプする、もしくはダンプしたファイルを別のDBサーバに転送/インポートする目的に使用できます(インポート先はMySQLに限定されません)。

使用方法はmysqldumpと基本的に同じですが、いくつか新しい機能が含まれています。多くのオプションが変わらず使用できますが、mysqldumpとの互換性に縛られることがないよう、一から開発されています。

主な新しい機能

  • ダンプ処理を高速化するために、データベースに含まれるスキーマおよびテーブルに対して並列処理が可能です
  • --include-*--exclude-*といったオプションを使用することで、dumpの対象を選択することができます(テーブル、ストアドプログラム、ユーザアカウント情報など)
  • ユーザアカウント情報に関して、MySQLのシステムテーブルに対するINSERTではなく、CREATE USERおよびGRANTとしてダンプすることができます(※1)
  • --compressオプションを使えば、クライアント・サーバ間で送信されるデータを圧縮することが出来ます。ネットワークの帯域、転送時間の節約になるため、リモートバックアップにおいて非常に便利な機能です。また、--compress-outputオプションで出力されたファイルの圧縮も可能です。ZLIB および LZ4 の圧縮アルゴリズムをサポートしています。
  • 処理の進捗状況を表示する機能があります。この機能はダンプ処理の状況を確認するのにとても便利です。あなたはダンプ対象のレコードの合計と、どれくらい完了しているかを確認できます。同時に、完了するまでの推定時間も表示されます。
  • ロード時間を短縮するため、データのINSERTが完了してからInnoDBのセカンダリインデックスを作成します。

※1 訳注:従来のmysqldumpでは、ユーザアカウント情報をdumpファイルに含めたい場合、mysql.user テーブルのINSERT文として出力する必要がありました

Exclude/Include オプション

この機能によって、ダンプ対象となるデータの選択や、必要なデータのフィルタリングがより簡単になります。ダンプしたいデータ(データべース、テーブル、トリガー、イベント、ストアドルーチン、ユーザ)を選択でき、ファイルサイズや実行時間、別ホストへの転送時間の節約につながります。

なお、相互に排他的なオプションも存在することに注意してください。例えば、--all-databasesオプションを使用している場合は、--exclude-databasesオプションが効果を持たなくなります。デフォルトの挙動として、mysqlpump--include-databasesオプションで明示的に指定されない限りは、以下のデータベースをダンプしません。

INFORMATION_SCHEMA, performance_schema, ndbinfo, sys

これらのオプションの値は、カンマ区切りのリストで指定されている必要があります。exclude/include系のオプションで、“%”を使用するとワイルドカードとして機能します。例として、--include-databases=t%,p%というオプションを使用すれば、" t " または " p " で始まる全データベースをダンプすることができます。

ユーザ、ストアドルーチン、トリガー、イベントに関しても、mysqlpumpには同様の--exclude-* / --include-*オプションが用意されており、使い方も同じです。ただし、いくつか注意点もあります。

  • トリガーは、デフォルトでダンプ対象に含まれます。その上で、--include-triggers / --exclude-triggersオプションを使って、ダンプ対象をフィルタリング出来ます。
  • ストアドルーチンとイベントは、デフォルトではダンプ対象に含まれません。そのため、--routines / --eventsオプション、もしくは各--include / --excludeオプションを使用する必要があります。
  • 同じ名前のストアドプロシージャとストアドファンクションが存在した場合、include/exclude の判定も両方に対して行われる点に注意してください

並列処理機能

この機能によって複数のデータベース、更にはその中の複数のテーブルを並列で処理することができます。mysqlpumpはデフォルトで、2スレッドで1つの処理キューを使用します。スレッドの数は、--default-parallelismオプションで増やすことができます。 追加のキューを使用しない限りは、全てのデータベース・テーブルは、デフォルトのキューのみを使用します。

キューを追加する場合は、--parallel-schemasオプションを使用します。つまり、「キューに対するスレッド数」と「キュー処理のためのデータベースのサブセット」の2つのパラメータが存在します。

例として、以下のようなコマンドが実行できます。

mysqlpump --include-databases=a,b,c,d,e,f,g,h --default-parallelism=3 --parallel-schemas=4:a,b

"c, d, e, f, g, h" のスキーマはデフォルトキュー(3スレッド使用)で処理されます。また、"a, b" のスキーマは別のキュー(4スレッド使用)で処理されます。なお、データべース名はカンマ区切りで書かれていなければいけません。

$ mysqlpump --parallel-schemas=4:example1,example2,example3 --parallel-schemas=3:example4,example5 > examples.sql
Dump progress: 0/1 tables, 250/261184 rows
Dump progress: 24/30 tables, 1204891/17893833 rows
Dump progress: 29/30 tables, 1755611/17893833 rows
Dump progress: 29/30 tables, 2309111/17893833 rows
...
Dump completed in 42424 milliseconds

ユーザアカウント

ユーザアカウント情報も、このツールを使って取得することができます。以下は、Percona Toolkitに含まれるpt-show-grantsmysqlpumpの違いに着目した比較になります。

デフォルトでは、mysqlpumpはユーザアカウントの定義情報を取得しません(たとえmysqlデータベースがダンプ対象であっても)。ユーザアカウント情報をダンプに含めたい場合は、--usersオプションを指定する必要があります。

以下は、ユーザアカウント情報のみをファイルに出力した場合の mysqlpumpの例となります。

$ mysqlpump --exclude-databases=% --exclude-triggers=% --users
-- Dump created by MySQL dump utility, version: 5.7.8-rc, linux-glibc2.5 (x86_64)
-- Dump start time: Thu Aug 27 17:10:10 2015
-- Server version: 5.7.8
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_TIME_ZONE=@@TIME_ZONE;
SET TIME_ZONE='+00:00';
SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
SET NAMES utf8;
CREATE USER 'msandbox'@'127.%' IDENTIFIED WITH 'mysql_native_password' AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT ALL PRIVILEGES ON *.* TO 'msandbox'@'127.%';
CREATE USER 'msandbox_ro'@'127.%' IDENTIFIED WITH 'mysql_native_password' AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT SELECT, EXECUTE ON *.* TO 'msandbox_ro'@'127.%';
CREATE USER 'msandbox_rw'@'127.%' IDENTIFIED WITH 'mysql_native_password' AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE ON *.* TO 'msandbox_rw'@'127.%';
CREATE USER 'rsandbox'@'127.%' IDENTIFIED WITH 'mysql_native_password' AS '*B07EB15A2E7BD9620DAE47B194D5B9DBA14377AD' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT REPLICATION SLAVE ON *.* TO 'rsandbox'@'127.%';
CREATE USER 'furrywall'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*AB8D50A9E3B8D1F3ACE85C54736B5BF472B44539' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT LOCK;
GRANT USAGE ON *.* TO 'furrywall'@'localhost';
CREATE USER 'msandbox'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT ALL PRIVILEGES ON *.* TO 'msandbox'@'localhost';
CREATE USER 'msandbox_ro'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT SELECT, EXECUTE ON *.* TO 'msandbox_ro'@'localhost';
CREATE USER 'msandbox_rw'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE ON *.* TO 'msandbox_rw'@'localhost';
CREATE USER 'root'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6C387FC3893DBA1E3BA155E74754DA6682D04747' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
CREATE USER 'testuser'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*6E543F385210D9BD42A4FDB4BB23FD2C31C95462' REQUIRE NONE PASSWORD EXPIRE INTERVAL 30 DAY ACCOUNT UNLOCK;
GRANT USAGE ON *.* TO 'testuser'@'localhost';
SET TIME_ZONE=@OLD_TIME_ZONE;
SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT;
SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS;
SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
-- Dump end time: Thu Aug 27 17:10:10 2015
Dump completed in 823 milliseconds

ご覧の通り、上の出力からmysqlpumpがセッション内で、タイムゾーンや文字セットとして既知の値を使用していることが分かります。これらの設定はユーザへの影響はありませんが、リストア先でのダンプファイルのリストア処理を正確に行うことができるようにしてくれます。

Percona Toolkit のpt-show-grantsと比較すると、mysqlpumpCREATE USER文を取得していることが分かります。このステートメントは、特にsql_mode変数の "NO_AUTO_CREATE_USERS"が設定されてる場合には、ユーザを再作成するための正しい(推奨される)方法です。もし、このsql_modeの設定が有効だと、pt-show-grantsは使えなくなります。

以下は、pt-show-grantsの例となります。

$ pt-show-grants --host 127.0.0.1 --port 5708 --user msandbox --ask-pass
Enter password:
-- Grants dumped by pt-show-grants
-- Dumped from server 127.0.0.1 via TCP/IP, MySQL 5.7.8-rc at 2015-08-27 17:06:52
-- Grants for 'furrywall'@'localhost'
GRANT USAGE ON *.* TO 'furrywall'@'localhost';
-- Grants for 'msandbox'@'127.%'
GRANT ALL PRIVILEGES ON *.* TO 'msandbox'@'127.%';
-- Grants for 'msandbox'@'localhost'
GRANT ALL PRIVILEGES ON *.* TO 'msandbox'@'localhost';
-- Grants for 'msandbox_ro'@'127.%'
GRANT EXECUTE, SELECT ON *.* TO 'msandbox_ro'@'127.%';
-- Grants for 'msandbox_ro'@'localhost'
GRANT EXECUTE, SELECT ON *.* TO 'msandbox_ro'@'localhost';
-- Grants for 'msandbox_rw'@'127.%'
GRANT ALTER, CREATE, CREATE TEMPORARY TABLES, DELETE, DROP, EXECUTE, INDEX, INSERT, LOCK TABLES, SELECT, SHOW DATABASES, UPDATE ON *.* TO 'msandbox_rw'@'127.%';
-- Grants for 'msandbox_rw'@'localhost'
GRANT ALTER, CREATE, CREATE TEMPORARY TABLES, DELETE, DROP, EXECUTE, INDEX, INSERT, LOCK TABLES, SELECT, SHOW DATABASES, UPDATE ON *.* TO 'msandbox_rw'@'localhost';
-- Grants for 'root'@'localhost'
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;
GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION;
-- Grants for 'rsandbox'@'127.%'
GRANT REPLICATION SLAVE ON *.* TO 'rsandbox'@'127.%';
-- Grants for 'testuser'@'localhost'
GRANT USAGE ON *.* TO 'testuser'@'localhost';

その他、補足事項

mysqldumpとの違いの一つに、mysqlpumpにはデフォルトで CREATE DATABASEステートメントが含まれていることがあります(--no-create-dbオプションを指定した場合を除く)。

これにより、ダンプのプロセスに重要な違いが生じます。それは、CREATE TABLEステートメントにデータベース名が含まれるようになる点です。そのため、あえて重複したテーブルを作成するために mysqlpumpを使うと問題が起きてしまいます。

前の記事
MySQLのレプリケーション手法の違い

Feed small 記事フィード