INDEX目次を開く +閉じる −
WordPress簡単移行を実行したら、この表示で止まった。
移行先でのデータベースの反映に失敗しました。 当サービスのデータベースサーバーがメンテナンス中などの場合、時間を空けてもう一度お試しください。
時間を空けて試しても、同じところで止まる。
この記事は、実際に4回連続で失敗したときの記録です。
よく案内される対処を一通り試して外れ、最後に原因を特定するまでの手順をまとめます。
先に結論
今回の原因は、移行元のデータベースに含まれていた2つのカラムの型定義でした。
`updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPdatetime 型に DEFAULT CURRENT_TIMESTAMP を指定する書き方です。移行元では動いていましたが、移行先がこれを受け付けず、テーブル作成の時点で失敗していました。
この2カラムの定義を書き換えたところ、同じ移行元・同じ手順で成功しました。
ただし、ここにたどり着くまでに9つの可能性を1つずつ潰しています。同じ原因とは限らないので、確認の順番を含めて共有します。
症状
移行を開始すると、まず「WordPressを移行しております」と表示されます。
しばらく待つと、失敗の画面に切り替わります。
ポイントは、エラーが「移行先での」と場所を明示していることです。
移行元への接続やログインが原因なら、ここまで到達しません。ファイルの取得は終わっていて、データベースを書き込む段階だけが失敗しています。
この時点で、確認すべき範囲はかなり絞れています。
まず確認したい2つのこと
1. 移行失敗データを削除してから再試行する
失敗した状態で再実行すると、前回の残骸が残ったまま処理が進みます。
画面には削除対象が明示されています。
- 移行先ディレクトリ配下のファイル
- 移行用に作成されたデータベース
- 移行用に作成されたデータベースユーザー
「入力画面に戻る」を押すと、これらが削除されます。
再試行の前に必ず実行してください。
なお、この失敗データは 「インストール済みWordPress一覧」には表示されません。
一覧が空でも残っています。残したまま新規インストールを実行すると、そちらもエラーになります。
2. 移行元のURLがhttpsになっているか
移行元サイトがhttpsで動いている場合、プロトコルの選択を間違えると別のエラーになります。
移行元WordPressのダッシュボードへのログインに失敗している可能性があります。 ユーザー名とパスワードに誤りがないことをご確認ください。 また、Basic認証やロボット認証が有効な場合は解除してください。
「入力画面に戻る」を押すと、プロトコルの選択が http に戻ることがあります。
再入力のたびに確認してください。
ただし、これはログイン段階のエラーです。「データベースの反映に失敗」とは別の症状なので、混同しないようにしてください。
実測で除外できた項目
ここからが本題です。以下はすべて、実際に確認して原因ではなかった項目です。
移行元サイトの稼働状況
トップページ、記事ページ、カテゴリ一覧、サイトマップの5つのパスを確認し、すべてHTTP 200でした。SSL証明書もドメイン名が一致し、有効期限内でした。
確認はブラウザでも構いませんが、コマンドなら一度に見られます。
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/kiji/移行元サーバーのアクセス制限
エックスサーバーには、WordPressに対するアクセス制限機能があります。国外アクセス制限、REST APIアクセス制限、XML-RPCアクセス制限などをすべてOFFにして実行しました。
結果は変わりませんでした。
データベースの容量
リビジョンを削除して、データベースを83MBから約15MBまで縮小しました。最大のテーブルでも2.84MB、最大の単一行は0.27MBです。
移行元の max_allowed_packet は約24MBだったので、サイズ超過は考えにくい状況でした。実際、縮小しても結果は同じでした。
ストレージエンジンと照合順序
全41テーブルがInnoDBでした。
照合順序は utf8mb4_unicode_520_ci が39テーブル、utf8_general_ci が2テーブルという混在状態でした。utf8mb4_unicode_520_ci はMariaDBに存在しないため有力な候補と考え、全テーブルを utf8mb4_general_ci に統一しました。
これも結果は変わりませんでした。
インデックスのキー長
VARCHAR(255) にプレフィックス指定なしのインデックスが4つありました。utf8mb4では1文字最大4バイトなので、キー長は1,020バイトになります。
InnoDBのインデックス最大キー長は、設定によって767バイトに制限されることがあります。そこで該当インデックスを191文字(764バイト)に張り直しました。
これも変わりませんでした。
移行先のデータベースサーバー
移行先でWordPressの新規インストールを実行したところ、成功しました。
データベースサーバー自体は正常に動作しています。この時点で、原因は移行データ側に絞られました。
移行先の環境が準備中である可能性
契約直後だったため、環境の反映が終わっていない可能性も考えました。
そこで、記事もプラグインも入っていない最小構成のWordPressを別に用意し、それを移行してみました。
成功しました。
移行先は正常に動作しています。原因は移行元のデータの中身にあると確定しました。
原因の特定方法
ここまでで、「移行元のデータのどこかが、移行先で受け付けられていない」ところまで絞れました。
具体的に何が問題なのかを知るには、エラーメッセージそのものを見る必要があります。
手動でインポートしてエラー番号を見る
簡単移行の画面には、詳細なエラーが表示されません。そこで、データベースを手動でインポートしてみます。
- 移行元でデータベースをエクスポートする
- 移行先のphpMyAdminからインポートする
すると、失敗した行とエラー番号が表示されます。今回表示されたのは、これでした。
#1067 - Invalid default value for 'updated'
つまり 「updated というカラムのデフォルト値が不正」 です。ここで原因が判明しました。
該当カラムを探す
エラーが出たテーブルの定義を見ると、次のようになっていました。
`updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPdatetime 型に DEFAULT CURRENT_TIMESTAMP を指定できるのは MySQL 5.6.5以降です。それ以前のMySQLやMariaDBでは、CURRENT_TIMESTAMP をデフォルト値にできるのは timestamp 型だけでした。
移行元はMySQL 5.7.29なので問題なく動きます。移行先がこの書き方を受け付けなければ、CREATE TABLE の時点でエラーになります。
データベース全体から同じ書き方を探すには、次のSQLが使えます。
SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, EXTRA
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND DATA_TYPE = 'datetime'
AND (COLUMN_DEFAULT LIKE '%CURRENT_TIMESTAMP%'
OR EXTRA LIKE '%CURRENT_TIMESTAMP%');今回は2件が該当しました。どちらもSEOプラグインが作成したテーブルです。WordPress本体が作るテーブルではありません。
対処方法
該当カラムの定義を、移行先でも通る形に変更します。
ALTER TABLE テーブル名
MODIFY updated datetime NOT NULL DEFAULT '0000-00-00 00:00:00';'0000-00-00 00:00:00' を選んだのは、移行先がこの値を受け入れることを確認済みだったためです。wp_posts や wp_comments など、WordPress本体のテーブルが同じデフォルト値を使っていて、そちらは正常に作成されていました。
変更前に必ずバックアップを取ってください。
失われるのは「更新時に時刻を自動記録する」挙動だけです。プラグインの主要機能には影響しませんでしたが、心配な場合は移行完了後に元の定義へ戻せます。
変更後の結果
この2カラムだけを変更し、他の条件はすべて失敗時と同じままで再実行しました。
移行ステータス:データ移行完了(100%)
成功しました。
移行先の5つのパスを確認したところ、すべてHTTP 200で、応答のバイト数も移行元と完全に一致していました。
確認する順番
同じ症状で困っている場合、次の順で確認するのが効率的です。
| 順番 | 確認すること | 理由 |
|---|---|---|
| 1 | 移行失敗データを削除したか | 残骸があると何度やっても同じ |
| 2 | 移行元URLのプロトコル(http / https) | 再入力のたびに戻ることがある |
| 3 | 移行元サイトが正常に表示されるか | 基本の確認 |
| 4 | 移行元サーバーのアクセス制限 | OFFにして試す |
| 5 | 移行先で新規インストールできるか | 移行先の正常性を切り分けられる |
| 6 | 最小構成のWordPressを移行できるか | データ側か環境側かを切り分けられる |
| 7 | 手動インポートでエラー番号を見る | ここで原因が判明することが多い |
5と6は特に効きます。
この2つで「移行先は正常」「原因はデータ側」まで絞れるので、当てずっぽうの試行錯誤を止められます。
それでも分からない場合
手動インポートのエラーを見ても判断がつかない場合は、サーバー会社のサポートに問い合わせてください。
その際、次の情報を添えると話が早く進みます。
- 移行元のMySQLバージョン、データベース容量、テーブル数
- 確認済みで問題がなかった項目(この記事の一覧が使えます)
- 新規インストールは成功するかどうか
- 手動インポート時のエラー番号
「何を確認して、何が問題なかったか」を先に伝えると、一般的な案内で終わらずに済みます。
よくある質問
時間を空ければ直りますか?
画面には「データベースサーバーがメンテナンス中などの場合、時間を空けてもう一度お試しください」と案内されます。ただし今回は、時間を空けても4回とも同じ段階で失敗しました。
データ側に原因がある場合、待っても解決しません。2回失敗したら、待つより切り分けに進む方が早いと考えています。
プラグインを停止すれば解決しますか?
簡単移行はファイルとデータベースをコピーする方式なので、移行中に移行元のプラグインは動作しません。
停止しても、プラグインが作成したテーブルは残ったままです。
原因がプラグインのテーブル定義にある場合、停止では解決しません。
削除すればテーブルごと消える場合もありますが、そのプラグインが必要なら現実的ではありません。
データベースの容量が原因ではないですか?
容量が極端に大きい場合は要因になり得ます。ただし今回は約15MB、最大の単一行も0.27MBで、縮小しても結果は変わりませんでした。
まず容量を確認し、数十MB程度であれば別の原因を探す方が近道です。
手動で移行した方が早いのでは?
原因が分からないまま時間を使うくらいなら、手動移行に切り替えるのは現実的な判断です。ファイルをFTPで転送し、データベースをphpMyAdminからインポートすれば移行できます。
ただし手動でインポートすると、今回のようにエラー番号が見えます。
原因を知る手段としても有効です。
まとめ
「移行先でのデータベースの反映に失敗しました」は、原因が画面に表示されないため、当てずっぽうの再試行に陥りやすいエラーです。
確実なのは、切り分けを先に進めることです。
- 移行先で新規インストールできるか → 移行先の正常性が分かる
- 最小構成のWordPressを移行できるか → データ側か環境側かが分かる
- 手動インポートでエラー番号を見る → 原因そのものが分かる
今回の原因は、SEOプラグインが作成したテーブルの datetime NOT NULL DEFAULT CURRENT_TIMESTAMP という定義でした。照合順序でもインデックス長でも容量でもありませんでした。
同じ表示が出ていても原因は異なる可能性があります。この記事の一覧を「確認済みで問題がなかった項目」として使い、残りを絞り込んでいくのが確実です。
サーバー移行にあわせて表示速度も見直す場合は、キャッシュが効いていない原因の調べ方もあわせてご覧ください。