古いMySQLの移行が地獄になる本当の理由

古いMySQLで作られたシステムを移行すると、なぜ壊れるのか

古いMySQLで動いていたシステムは、そのまま新しいMySQLに載せ替えると高確率で動かなくなります。
しかも「性能が落ちる」とか「一部機能が変わる」といったレベルではありません。SQLは同じなのに、アプリがエラーを出して停止します。

移行作業を始めた直後、開発者は混乱します。
DBを入れ替えただけなのに、ログインすらできないという現象が普通に起きるからです。

これは珍しいトラブルではありません。
古いMySQLからの移行では、むしろ典型的な現象です。

理由は単純です。
古いMySQLと新しいMySQLは、同じ名前のデータベースですが同じ挙動をするソフトではないからです。

壊れるのは「データ」ではなく「前提」

多くの人は、データ移行の問題だと考えます。
しかし実際に壊れるのはテーブルではありません。壊れるのは、アプリケーションが暗黙に依存していたMySQLの仕様です。

古いMySQLの時代、次のようなSQLが普通に動いていました。

SELECT id, name, MAX(created_at)
FROM users
GROUP BY id;

このSQLは標準SQLとしては正しくありません。
GROUP BYしているのに、nameが集約されていないためです。

それでも昔のMySQLはエラーにしませんでした。
とりあえず値を返す設計だったからです。

そしてアプリケーションは、それを仕様だと信じて作られていきました。
ここが移行時に爆発するポイントです。

新しいMySQLは“間違い”を許さない

MySQL5.7以降では ONLY_FULL_GROUP_BY がデフォルトで有効になりました。
すると、先ほどのSQLは不正なSQLとして扱われます。

移行時に起きる現象はだいたい次のようになります。

  • 一覧画面が表示されない
  • ログイン後にエラー画面になる
  • 集計画面が全部落ちる
  • ORMが例外を出す

原因はコードのバグではありません。
MySQLが厳密な動作に変わったことです。

なぜ古いMySQLは寛容だったのか

昔のMySQLは、現在のようなRDBMSの厳密性を最優先にしていませんでした。
目的は「Webサイトをとにかく動かすこと」です。

当時の主な用途は次の通りです。

  • 掲示板
  • 簡易CMS
  • ECカート
  • 会員管理

重要だったのは整合性より停止しないことでした。
そのためMySQLは、SQLの誤りを指摘するよりそれらしく結果を返す挙動を選びました。

便利でしたが、代償もありました。
アプリケーションがDBの曖昧な挙動に依存してしまったのです。

移行時に起きる典型的なトラブル

1. GROUP BY問題**

集計画面や管理画面が壊れます。
特に一覧の最新データ表示ロジックで発生しやすいです。

2. 日付の扱い**

INSERT INTO orders (created_at) VALUES ('0000-00-00');

古いMySQLでは許可されていましたが、新しいMySQLでは拒否されます。
これが原因で会員登録や注文登録が止まるケースがあります。

3. 文字コード**

古いDBは多くが utf8(3バイト)です。
絵文字や一部の記号を保存しようとすると例外になります。

これはアプリのバグではなく、データベース仕様の差です。

ORMが壊れる理由

最近のシステムではORMが使われます。
しかしORMは「正しいSQLが通る」前提で設計されています。

古いMySQLで通っていたSQLが5.7以降で例外になると、ORMは想定外のDBエラーとして扱います。
結果としてアプリケーション障害になります。

開発者はアプリケーションロジックを疑いますが、原因はSQLモードです。

さらに危険なポイント:認証方式

MySQL8では認証方式が変更されました。
mysql_native_password から caching_sha2_password へ変わっています。

古いドライバや古いアプリは接続できません。

症状は次の通りです。

  • DB接続エラー
  • 画面が真っ白
  • アプリが起動しない

コードの問題に見えますが、実際はDB仕様の違いです。

対策:最初にやるべきこと

移行時にいきなり本番データを投入するのは危険です。
先にやるべきはSQLの検査です。

新しいMySQLで次を有効にします。

  • ONLY_FULL_GROUP_BY
  • STRICT_TRANS_TABLES
  • NO_ZERO_DATE

その状態でアプリを起動します。
ここで出るエラーは、移行後に必ず問題になります。

つまり移行とはデータコピーではありません。
アプリケーションの前提を確認する作業です。

移行が成功するプロジェクトの特徴

うまくいく移行には共通点があります。

  • DB移行をインフラ作業だと思っていない
  • SQLログを確認している
  • 新DBで事前検証している

逆に失敗するケースはほぼ同じです。
「DBを入れ替えるだけ」と考えたときです。

なぜ地獄になるのか

古いMySQLはアプリケーションに優しいデータベースでした。
新しいMySQLはデータに正直なデータベースです。

この違いは小さく見えますが、意味は大きいです。

アプリケーションは仕様書ではなく、実際に動いた挙動に合わせて作られます。
多くの古いシステムは、MySQLの寛容さに依存して成立しています。

移行が難しいのはコードが古いからではありません。
本当に移行しているのはデータベースではなく、過去の前提条件です。

移行作業とはバージョンアップではなく、システムが何に依存していたかを知る作業になります。