INDEX目次を開く +

WordPress簡単移行を実行したら、この表示で止まった。

移行先でのデータベースの反映に失敗しました。 当サービスのデータベースサーバーがメンテナンス中などの場合、時間を空けてもう一度お試しください。

時間を空けて試しても、同じところで止まる。

この記事は、実際に4回連続で失敗したときの記録です。

よく案内される対処を一通り試して外れ、最後に原因を特定するまでの手順をまとめます。

先に結論

今回の原因は、移行元のデータベースに含まれていた2つのカラムの型定義でした。

`updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

datetime 型に DEFAULT CURRENT_TIMESTAMP を指定する書き方です。移行元では動いていましたが、移行先がこれを受け付けず、テーブル作成の時点で失敗していました。

この2カラムの定義を書き換えたところ、同じ移行元・同じ手順で成功しました。

ただし、ここにたどり着くまでに9つの可能性を1つずつ潰しています。同じ原因とは限らないので、確認の順番を含めて共有します。

症状

移行を開始すると、まず「WordPressを移行しております」と表示されます。

WordPress簡単移行の実行中画面。移行ステータスが待機中0パーセントと表示されている

しばらく待つと、失敗の画面に切り替わります。

移行先でのデータベースの反映に失敗しましたという赤いエラーと、移行ステータス中止、移行失敗データが削除されますという案内が表示されている

ポイントは、エラーが「移行先での」と場所を明示していることです。

移行元への接続やログインが原因なら、ここまで到達しません。ファイルの取得は終わっていて、データベースを書き込む段階だけが失敗しています。

この時点で、確認すべき範囲はかなり絞れています。

まず確認したい2つのこと

1. 移行失敗データを削除してから再試行する

失敗した状態で再実行すると、前回の残骸が残ったまま処理が進みます。

画面には削除対象が明示されています。

  • 移行先ディレクトリ配下のファイル
  • 移行用に作成されたデータベース
  • 移行用に作成されたデータベースユーザー

「入力画面に戻る」を押すと、これらが削除されます。

再試行の前に必ず実行してください。

なお、この失敗データは 「インストール済みWordPress一覧」には表示されません。

一覧が空でも残っています。残したまま新規インストールを実行すると、そちらもエラーになります。

2. 移行元のURLがhttpsになっているか

移行元サイトがhttpsで動いている場合、プロトコルの選択を間違えると別のエラーになります。

移行元WordPressのダッシュボードへのログインに失敗している可能性がありますという赤いエラーメッセージが表示された入力画面

移行元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にして実行しました。

エックスサーバーのWordPressセキュリティ設定画面。IPアドレス制限、国外アクセス制限、REST API制限などがすべて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を別に用意し、それを移行してみました。

成功しました。

移行先は正常に動作しています。原因は移行元のデータの中身にあると確定しました。

原因の特定方法

ここまでで、「移行元のデータのどこかが、移行先で受け付けられていない」ところまで絞れました。

具体的に何が問題なのかを知るには、エラーメッセージそのものを見る必要があります。

手動でインポートしてエラー番号を見る

簡単移行の画面には、詳細なエラーが表示されません。そこで、データベースを手動でインポートしてみます。

  1. 移行元でデータベースをエクスポートする
  2. 移行先のphpMyAdminからインポートする

すると、失敗した行とエラー番号が表示されます。今回表示されたのは、これでした。

#1067 - Invalid default value for 'updated'

つまり updated というカラムのデフォルト値が不正」 です。ここで原因が判明しました。

該当カラムを探す

エラーが出たテーブルの定義を見ると、次のようになっていました。

`updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

datetime 型に 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_postswp_comments など、WordPress本体のテーブルが同じデフォルト値を使っていて、そちらは正常に作成されていました。

変更前に必ずバックアップを取ってください。

失われるのは「更新時に時刻を自動記録する」挙動だけです。プラグインの主要機能には影響しませんでしたが、心配な場合は移行完了後に元の定義へ戻せます。

変更後の結果

この2カラムだけを変更し、他の条件はすべて失敗時と同じままで再実行しました。

WordPress簡単移行の完了画面。移行ステータスがデータ移行完了100パーセントと表示されている

移行ステータス:データ移行完了(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 という定義でした。照合順序でもインデックス長でも容量でもありませんでした。

同じ表示が出ていても原因は異なる可能性があります。この記事の一覧を「確認済みで問題がなかった項目」として使い、残りを絞り込んでいくのが確実です。

サーバー移行にあわせて表示速度も見直す場合は、キャッシュが効いていない原因の調べ方もあわせてご覧ください。