2026年8月3日
2026年8月3日
MySQLデータベースを別サーバーへ移行する手順|mysqldumpでの書き出し・取り込み・確認
データベースを別のサーバーへ移す方法はいくつかありますが、数GB程度までのMySQL・MariaDBなら、mysqldump でSQLファイルに書き出し、移行先で読み込む方法がもっとも手順が少なく、バージョンが違うサーバーの間でも使えます。この記事では、移行前の確認から、書き出し、転送、取り込み、照合、アプリの切り替えまでを順に説明します。MySQL 8.0・8.4とMariaDB 10.6以降を前提にしています(2026年10月時点)。
例では、移行元と移行先のデータベース名を wpdb、アプリ用のユーザーを wpuser とします。
移行前に確認すること
移行元と移行先で、次の項目を確認しておきます。
-- サーバーの種類とバージョン
SELECT VERSION();
-- データベースの文字コードと照合順序
SELECT default_character_set_name, default_collation_name
FROM information_schema.schemata WHERE schema_name = 'wpdb';
-- データベースの大きさ(MB)とストレージエンジン
SELECT engine, COUNT(*) AS tables,
ROUND(SUM(data_length + index_length) / 1024 / 1024) AS size_mb
FROM information_schema.tables WHERE table_schema = 'wpdb'
GROUP BY engine;
- 移行先のバージョンが移行元より古い、またはMySQLからMariaDBへ移す場合は、照合順序などで取り込みエラーが出ることがあります(後述)
- 移行先のディスクに、データベースの大きさとダンプファイルを置ける空きがあるか
- 移行中に書き込みが入ると、その分は移行先に入りません。アプリを止めるかメンテナンス表示にする時間を決めておきます
mysqldumpで書き出す
パスワードをコマンドラインに書くと、ほかのユーザーからプロセス一覧で見えたり、シェルの履歴に残ったりします。-p だけを付けて対話で入力するか、オプションファイルを使います。
# 自分だけが読めるオプションファイルを作る(パスワードは自分のものに置き換える)
cat > ~/.migrate.cnf << 'EOF'
[client]
user=root
password=パスワード
EOF
chmod 600 ~/.migrate.cnf
書き出します。--defaults-extra-file は最初のオプションとして書きます。
mysqldump --defaults-extra-file=~/.migrate.cnf \
--single-transaction \
--routines --triggers --events \
--default-character-set=utf8mb4 \
--no-tablespaces \
--databases wpdb | gzip > wpdb_$(date +%Y%m%d%H%M).sql.gz
| オプション | 意味 |
|---|---|
--single-transaction |
InnoDBのテーブルを、書き出し開始時点のそろった状態で書き出す。テーブルをロックしないので、書き出し中もアプリは動く |
--routines --events |
ストアドプロシージャ・関数とイベントも書き出す(既定では含まれない) |
--triggers |
トリガーを書き出す(既定で有効。明示しておくと意図がわかる) |
--default-character-set=utf8mb4 |
文字化けを防ぐため、接続の文字コードを指定する |
--no-tablespaces |
表領域の情報を書き出さない。MySQL 8.0.21以降は、これを付けないと PROCESS 権限の無いユーザーでエラーになる |
--databases wpdb |
CREATE DATABASE と USE 文を含めて書き出す。付けない場合は、取り込み時にデータベース名を指定する |
--single-transaction がそろった状態を保証するのはInnoDBのテーブルだけです。MyISAMのテーブルが残っている場合は、書き出しの間アプリを止めてください。
環境によって必要なオプション
- MySQLでGTIDを有効にしている場合: ダンプにGTIDの設定文が入り、移行先で取り込めないことがあります。レプリケーションを組むのでなければ
--set-gtid-purged=OFFを付けます - MySQL 8.0以降の
mysqldumpで、MySQL 5.7やMariaDBのサーバーから書き出す場合:Unknown table 'COLUMN_STATISTICS'というエラーが出たら--column-statistics=0を付けます - MariaDB 10.5以降は
mariadb-dumpとmariadbが正式なコマンド名です。mysqldumpやmysqlという名前が入っていない環境では、こちらの名前で同じオプションを使います(MySQL固有の--set-gtid-purgedと--column-statisticsは除く)
移行先へ転送する
scp や rsync で転送し、転送前後でチェックサムを比べます。
# 移行元で
sha256sum wpdb_202610311200.sql.gz
scp wpdb_202610311200.sql.gz admin@203.0.113.20:/tmp/
# 移行先で(移行元と同じ値になることを確認する)
sha256sum /tmp/wpdb_202610311200.sql.gz
ダンプファイルにはデータベースの中身がすべて入っています。個人情報を含む場合は、作業が終わったら移行元・移行先の両方から削除してください。
移行先でデータベースとユーザーを作る
移行先のサーバーで、管理者としてログインして作業します。--databases を付けて書き出した場合は、ダンプの中の CREATE DATABASE でデータベースが作られますが、文字コードと照合順序を自分で指定したい場合は先に作っておきます。
CREATE DATABASE IF NOT EXISTS wpdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'アプリ用のパスワード';
GRANT ALL PRIVILEGES ON wpdb.* TO 'wpuser'@'localhost';
照合順序は、移行元で確認したものに合わせます。移行元がMySQL 8.0の既定(utf8mb4_0900_ai_ci)で、移行先もMySQL 8.0以降なら、そのままでかまいません。ユーザーのホスト部分(localhost など)は、移行先でアプリが接続してくる場所に合わせます。
取り込む
gunzip < /tmp/wpdb_202610311200.sql.gz | mysql --defaults-extra-file=~/.migrate.cnf --default-character-set=utf8mb4
--databases を付けずに書き出したファイルの場合は、取り込み先のデータベース名を最後に指定します。
gunzip < /tmp/wpdb_202610311200.sql.gz | mysql --defaults-extra-file=~/.migrate.cnf --default-character-set=utf8mb4 wpdb
よくあるエラー
| エラー | 原因と対処 |
|---|---|
Unknown collation: 'utf8mb4_0900_ai_ci' |
MySQL 8.0以降のダンプを、この照合順序を持たないMariaDBやMySQL 5.7に取り込んだ。ダンプ内の照合順序を置き換えてから取り込む(下のコマンド) |
Access denied; you need (at least one of) the SUPER ... privilege(s) |
ビュー・トリガー・ストアドプロシージャの DEFINER に、移行先に無いユーザーや、自分以外のユーザーが指定されている。移行先に同じユーザーを作ってから管理者で取り込むか、DEFINER を取り込むユーザーに合わせる |
Got a packet bigger than 'max_allowed_packet' bytes |
1つの行やINSERT文がサーバーの上限を超えた。移行先の [mysqld] の max_allowed_packet を大きくして再起動する(例: 256M) |
ERROR 1046 (3D000): No database selected |
--databases を付けずに書き出したファイルを、データベース名を指定せずに取り込んだ |
# 照合順序を置き換える(展開してから置き換え、元のファイルは残す)
gunzip -c /tmp/wpdb_202610311200.sql.gz > /tmp/wpdb.sql
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' /tmp/wpdb.sql
mysql --defaults-extra-file=~/.migrate.cnf --default-character-set=utf8mb4 < /tmp/wpdb.sql
DEFINER に指定されたユーザーと異なるユーザーで取り込むには、MySQLでは SUPER か SET_USER_ID(MySQL 8.2以降は SET_ANY_DEFINER)の権限が必要です。移行先でもアプリと同じユーザー名・ホストのアカウントを先に作っておくと、この問題は起きにくくなります。
移行できたかを照合する
テーブルの数と、各テーブルの行数を、移行元と移行先で比べます。information_schema.tables の table_rows はInnoDBでは概算値なので、正確に比べるには COUNT(*) を使います。
# 移行元・移行先の両方で実行し、出力を diff で比べる
for t in $(mysql --defaults-extra-file=~/.migrate.cnf -N -e "SHOW TABLES" wpdb); do
echo "$t $(mysql --defaults-extra-file=~/.migrate.cnf -N -e "SELECT COUNT(*) FROM \`$t\`" wpdb)"
done > counts_$(hostname).txt
ストアドプロシージャやトリガーを使っている場合は、移行先でも存在するかを確認します。
SHOW TRIGGERS FROM wpdb;
SHOW PROCEDURE STATUS WHERE Db = 'wpdb';
SHOW FUNCTION STATUS WHERE Db = 'wpdb';
アプリを切り替える
- アプリをメンテナンス表示にするなどして、移行元への書き込みを止める
- 最後のダンプを取り、転送して取り込み、照合する
- アプリの接続先(ホスト名、ユーザー名、パスワード)を移行先に変える
- 動作を確認してから、メンテナンス表示を解除する
移行元のサーバーは、問題が出たときに戻せるよう、しばらく残しておきます。
WordPressの場合は、wp-config.php の DB_NAME、DB_USER、DB_PASSWORD、DB_HOST を移行先の値にします。サイトのドメインも変わる場合は、データベース内のURLを wp search-replace で置き換えます。手順は下の関連記事を参照してください。
大きなデータベースの場合
数十GBを超えると、mysqldump の書き出しと取り込みには時間がかかります。並列で処理できるツールとして、MySQL ShellのダンプユーティリティやMydumperがあります。また、同じ種類・同じ系列のバージョンの間なら、レプリケーションで移行先に同期してから切り替えると、停止時間を短くできます。いずれも、使っているバージョンの公式ドキュメントで手順を確認してください。
まとめ
- 移行前に、バージョン、文字コードと照合順序、大きさ、停止できる時間を確認する
mysqldump --single-transaction --routines --triggers --events --no-tablespacesで書き出し、パスワードはオプションファイルで渡す- 転送したらチェックサムを比べ、移行先で文字コードを合わせたデータベースとユーザーを作ってから取り込む
- 照合順序、
DEFINER、max_allowed_packetのエラーはよく出るので、対処を知っておく - テーブルごとの
COUNT(*)を比べてから、アプリの接続先を切り替える
関連記事: