MySQL道普請便り

第15回mysqldumpを使ってバックアップする

そろそろ新年度を迎えて新しいPCやサーバを受け取る事もあるかと思いますが、そういった場合問題になるのがデータベースの移行です。とくに開発中に自分で作成したダミーのデータ等を手動で作成していた場合は、データに愛着があったり特殊なケースを検証するためのものを作成していたり等、そのまま移行したいこともあると思います。MySQLのデータファイルをそのまま新しいPCに移行して動く場合は良いのですが、万が一何か問題が起こった場合には復旧することは難しいでしょう。

そこで、今回はmysqlに標準でインストールされているmysqldumpを使ってテキストベースのバックアップを行ってみたいと思います。

デモンストレーション環境

今回使用するmysqldumpに関してはMac OS X(10.10.5)の上にHomebrewを用いて構築した5.7.11上での作業とします。使用するデータは第2回 MySQLにはじめてのデータを入れてみるで紹介されている郵便番号のデータベースを元にお話をさせていただきます。以下のようにzipcodeを作成した状態になってます。

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

mysqldumpを使ってみる

まずは一番シンプルにスキーマ全体をバックアップしてみましょう。以下のコマンドでローカルにあるMySQLからバックアップを取得します。またmysqlコマンドを使う時と同様に、host名やポートuser名等を指定することができます。今回はzipcodeデータベースの内容をバックアップしたいので、zipcodeデータベースを指定してます。

$ mysqldump -uroot -h127.0.0.1 -P3306 zipcode > backup.sql

出力されたbackup.sqlの中身を確認してみましょう。出力されたファイルは以下のような構成になってます。出力されるファイルが大きいため、変数宣言部分とテーブル宣言部分とデータ句に分割して説明をしていきます。

出力されたファイルの冒頭部分を見てみると、mysqldumpをどのバージョンのどういった設定のMySQLに対して行ったのかを確認することができます。またこれらの設定は読み込まれる際に自動で適用されます。そのためコメントだからと言って削除してしまうと挙動が変わってしまうことになるのでご注意ください。設定の内容が知りたい方は公式のドキュメントのコメントの構文をご覧になってください。

-- MySQL dump 10.13  Distrib 5.7.11, for osx10.10 (x86_64)
--
-- Host: localhost    Database: zipcode
-- ------------------------------------------------------
-- Server version       5.7.11

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

---省略---

続いてテーブルの宣言部分になります。ここでは最初にzipcodeテーブルが存在する場合にDROPを行ってからCREATEテーブルを行ってます。このことにより、バックアップから復旧した際にもし何らかの理由で同名のテーブルが存在していた場合でも問題なく復旧が行われます。

--
-- Table structure for table `zipcode`
--

DROP TABLE IF EXISTS `zipcode`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `zipcode` (
  `code` varchar(12) NOT NULL,
  `old_zipcode` varchar(5) NOT NULL,
  `zip_code` varchar(7) NOT NULL,
  `prefecture_kana` varchar(255) NOT NULL,
  `city_kana` varchar(255) NOT NULL,
  `town_kana` varchar(255) NOT NULL,
  `prefecture` varchar(128) NOT NULL,
  `city` varchar(128) NOT NULL,
  `town` varchar(128) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/*!40101 SET character_set_client = @saved_cs_client */;

最後にデータをinsertしている部分を確認してみます。以下のようにバルクインサートが行われていきます。

--
-- Dumping data for table `zipcode`
--

LOCK TABLES `zipcode` WRITE;
/*!40000 ALTER TABLE `zipcode` DISABLE KEYS */;
INSERT INTO `zipcode` VALUES ('01610','056  ','0560001','ホッカイドウ','ヒダカグンシンヒダカチョウ','シズナイメナ(ソノタ)','北海道','日高郡新ひだか町','静>内目名(その他)'),('01610','056  ','0560024','ホッカイドウ','ヒダカグンシンヒダカチョウ','シズナイヤマテチョウ','北海道','日高郡新ひだか町','静内山手町'),('01610','056  ','0560018','ホッカイドウ','ヒダカグンシンヒダカチョウ','シズナイヨシノチョウ','北海道','日高郡新ひだか町','静内吉野町'),  ---省略---

このようにまずはSQLベースでバックアップを取ることができました。

バックアップから復旧してみる

今回取得したバックアップは先に確認したとおり、中身は全てSQLで構成されています。そのため、MySQLに対してバックアップ時に作成したSQLを以下のように実行することで、復旧することができます。

今回はzipcode2というデータベースを作成して、そこにデータを復元してみましょう。

mysql> create database zipcode2;
Query OK, 1 row affected (0.00 sec)
mysql> exit

$ mysql -uroot zipcode2 < backup.sql

それでは結果を確認してみましょう。SHOW CREATE TABLEを見ると、テーブルに関しては問題なく適用されているように見えます。

$ mysql -uroot
mysql> USE zipcode2
mysql> SHOW CREATE TABLE zipcode;

| zipcode | CREATE TABLE `zipcode` (
  `code` varchar(12) NOT NULL,
  `old_zipcode` varchar(5) NOT NULL,
  `zip_code` varchar(7) NOT NULL,
  `prefecture_kana` varchar(255) NOT NULL,
  `city_kana` varchar(255) NOT NULL,
  `town_kana` varchar(255) NOT NULL,
  `prefecture` varchar(128) NOT NULL,
  `city` varchar(128) NOT NULL,
  `town` varchar(128) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |

続いてデータはどうでしょうか?

mysql> USE zipcode
mysql> SELECT COUNT(*) FROM zipcode;
+----------+
| COUNT(*) |
+----------+
|   123920 |
+----------+
1 row in set (0.03 sec)

mysql> USE zipcode2
mysql> SELECT COUNT(*) FROM zipcode;
+----------+
| COUNT(*) |
+----------+
|   123920 |
+----------+
1 row in set (0.04 sec)

以上のような結果となり、同数のデータが入っていることがわかりました。

ここではバックアップから復旧する方法を確認できました。次項からmysqldumpの詳細な使い方を紹介していきます。

テーブル構造をバックアップする

mysqldumpをそのまま使うとテーブル構造とデータがバックアップされるのですが、たとえば本番のコピーの開発環境を作りたいなど、テーブル構造だけ必要な場合があります。その場合は以下のように--no-dataオプションを付けて上げることで、データ構造なしのSQLを取得することができます。

$ mysqldump -uroot --no-data zipcode > backup.sql

上記のファイルとほぼ同様の出力ファイルのため割愛しますが、backup.sqlを見てみるとINSERT文がなくなっていることがわかります。上記の例では--no-dataをつけることでデータを出力しないように設定しましたが、他にも--no-create-infoといったオプションをつけることで、今度は逆にデータだけのバックアップファイルを作成できます。

特定のテーブルだけバックアップをする

今回はzipcodeテーブルだけしかありませんが、特定のテーブルのみダンプ対象にしたい場合はその後ろにテーブル名を追加していくことで必要なテーブルだけバックアップをすることもできます。

$ mysqldump -uroot --no-data zipcode zipcode> backup.sql

コマンドの例

$ mysqldump -uroot schema1 table1 table2

特定の条件に合致するものをバックアップする

mysqldumpは--whereオプションを使うことで、条件に合致するデータだけをバックアップすることができます。

$ mysqldump --where "prefecture = '東京都'" zipcode > backup.sql

バックアップ結果を開いてみると以下のとおりになっていて、今回--whereオプションで指定した東京都のみが表示されていることがわかります。

 ---省略---
INSERT INTO `zipcode` VALUES ('13101','100  ','1000000','トウキョウト','チヨダク','イカニケイサイガナイバアイ','東京都','千代田区','以下に掲載がない場合'),('13101','102  ','1020072','トウキョウト','チヨダク','イイダバシ','東京都','千代田区','飯田橋'),('13101','102  ','1020082','トウキョウト','チヨダク','イチバンチョウ','東京都','千代田区','一番町'),('13101','101  ','1010032','トウキョウト','チヨダク','イワモトチョウ','東京都','千代田区','岩本町'),('13101','101  ','1010047','トウキョウト','チヨダク','ウチカンダ','東京都','千代田区','内神田'),('13101','100  ','1000011','トウキョウト','チヨダク','ウチサイワイチョウ','東京都','千代田区','内幸町'),('13101','100  ','1000004','トウキョウト','チヨダク','オオテマチ(ツギノビルヲノゾク)','東京都','千代田区','大手町(次のビルを除く)'),('13101','100  ','1006890','トウキョウト','チヨダク','オオテマチジェイエイビル(チカイ・カイソウフメイ)','東京都','千代田区','大手町JAビル(地>階・階層不明)'),('13101','100  ','1006801','トウキョウト','チヨダク','オオテマチジェイエイビル(1カイ)','東京都','千代田区','大手町JAビル(1階)'),('13101','100  ','1006802','トウキョウト','チヨダク','オオテマチジェイエイビル(2カイ)','東京都','千代田区','大手町JAビル(2階)'),  ---省略---

この他の詳しいオプションが気になる他はmysqldumpの公式ドキュメントをご覧になってください。

まとめ

mysqldumpを使ってテキストベースでのバックアップが行えるようになりました。

今時のWebフレームワークだとマイグレーション機能が最初から使える状態になっているものなどもありますが、たとえば開発人員が増えた時にMySQLをインストールしてもらい、mysqldumpを使いバックアップしたSQLをロードしてもらうだけでセットアップが済むなど楽ができます。またTRUNCATEやDROPやDELETEなどの破壊的な操作を行う前に保存しておけば、ロードし直すことで何度も試せます。

またテキストベースということで、エンジニアとして自分の馴染みがある形式でバックアップをとっておけることもメリットのひとつです。出力されたファイルは、データを直接追加、修正、削除なども簡単に行えます。MySQL以外のRDBMSを試してみたいと思った時にも、比較的簡単にデータとして使用することができます。

みなさんもぜひmysqldumpをして、一度MySQLの中を覗いてみてはいかがでしょうか?

おすすめ記事

記事・ニュース一覧