- 古いMySQLで作られたシステムを移行すると、なぜ壊れるのか
- 壊れるのは「データ」ではなく「前提」
- 新しいMySQLは“間違い”を許さない
- なぜ古いMySQLは寛容だったのか
- 移行時に起きる典型的なトラブル
- ORMが壊れる理由
- さらに危険なポイント:認証方式
- 対策:最初にやるべきこと
- 移行が成功するプロジェクトの特徴
- なぜ地獄になるのか
古い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の寛容さに依存して成立しています。
移行が難しいのはコードが古いからではありません。
本当に移行しているのはデータベースではなく、過去の前提条件です。
移行作業とはバージョンアップではなく、システムが何に依存していたかを知る作業になります。