OSのファイルシステムとテーブル名の依存関係
開発環境と本番環境でSQLの実行結果が異なる場合、その原因の多くはMySQLのテーブル名の大文字・小文字区別(Case Sensitivity)にあります。MySQLはテーブルのメタデータやデータをOSのファイルシステム上に物理的に保存します。Linux(ext4など)はファイル名の大文字・小文字を厳密に区別しますが、Windowsは区別しません。
例えば、Linux環境で CREATE TABLE UserData (...) を実行した場合、内部的には UserData という名前のファイルが作成されます。そのため、SELECT * FROM userdata を実行してもファイルが見つからずエラーになります。一方でWindowsでは同一ファイルとして認識されます。このクロスプラットフォームの差異を吸収し、統一的な挙動を提供するために lower_case_table_names パラメータが用意されています。
制御パラメータ:lower_case_table_names
このパラメータはMySQLの起動時に読み込まれ、テーブル名の保存および検索時の挙動を決定します。
- 0: 大文字・小文字を区別します。作成時のままのケースで保存され、検索時も厳密なマッチングが要求されます(Linuxのデフォルト)。
- 1: 大文字・小文字を区別しません。保存時および検索時にすべて小文字に正規化されます(Windowsのデフォルト)。
- 2: 保存時は作成時のケースを維持しますが、検索時のみ小文字に変換してマッチングを行います(Linux以外のOSで有効)。
※ このパラメータはMySQLの起動前に設定する必要があり、変更後は必ずサービスの再起動が求められます。また、既存のデータベースと新しいルール間に不整合が生じると、テーブルがアクセス不能になるリスクがあります。
バージョン5.7と8.0の決定的な挙動差異
両バージョンとも同じパラメータを使用しますが、設定の柔軟性において大きな違いがあります。
| バージョン | Linuxデフォルト | Windowsデフォルト | 設定の制限事項 |
|---|---|---|---|
| 5.7 | 0(区別する) | 1(区別しない) | 起動後でも設定ファイルを変更し、再起動すれば反映可能 |
| 8.0 | 0(区別する) | 1(区別しない) | 初期化(初回起動)後は変更不可。初期化前に必ず設定する必要がある |
MySQL 8.0 では、データディレクトリの初期化段階でこのパラメータの値が内部メタデータに固定されます。そのため、初期化後に設定ファイルを書き換えても無視されます。
環境・バージョン別の設定手順
MySQL 5.7 の設定
一時的な変更(再起動で無効化)
MySQLクライアントに接続し、システム変数を直接更新します。
SET @@GLOBAL.lower_case_table_names = 1;
※ 反映にはセッションの再接続が必要です。サーバー再起動後はデフォルト値に戻ります。
永続的な変更
- 設定ファイル(Linux:
/etc/my.cnf、Windows:my.ini)を開きます。 [mysqld]セクションに以下を追記します。lower_case_table_names = 1- MySQLサービスを再起動します(Linux:
systemctl restart mysqld)。 - 設定確認:
SHOW VARIABLES LIKE 'lower_case_table_names';
MySQL 8.0 の設定
シナリオA:新規インストール(未初期化)
- 設定ファイルの
[mysqld]にlower_case_table_names = 1を追記します。 - 初期化コマンドを実行します。
mysqld --defaults-file=/etc/mysql/my.cnf --initialize - サービスを起動すれば、パラメータが有効になった状態で稼働します。
シナリオB:既存環境の変更(再初期化が必要)
8.0の既存環境で値を変更する場合、データを退避させて初期化からやり直す必要があります。
- 全データベースのバックアップを取得します。
mysqldump -u root -p --all-databases --single-transaction > complete_db_snapshot.sql - MySQLサービスを停止します。
- データディレクトリ(
datadirで指定されたパス、例:/var/lib/mysql)を完全に削除します。 - 設定ファイルに
lower_case_table_names = 1を追記します。 - データベースを再初期化し、サービスを起動します。
- バックアップからデータをリストアします。
mysql -u root -p < complete_db_snapshot.sql
運用上のベストプラクティス
- 環境の統一: Linuxサーバーでは
lower_case_table_names = 1に設定し、Windows開発環境と同一の挙動に統一することを推奨します。 - 命名規則: パラメータの設定に関わらず、DDLやアプリケーションコード内のテーブル名はすべて小文字(またはスネークケース)で統一します。
- 既存テーブルの修正: 既に大文字混在のテーブルがある場合、以下のようにリネームして小文字に揃えます。
RENAME TABLE UserProfiles TO user_profiles; - バージョンアップ時の注意: 5.7から8.0へ移行する際、移行先の8.0初期化前に5.7と同じパラメータ値が設定されているか必ず確認してください。
補足:カラム名と照合順序(Collation)の仕組み
テーブル名の大文字・小文字区別はOSと lower_case_table_names に依存しますが、カラム名の区別ルールは異なります。カラム名の敏感性は、ストレージエンジンではなく照合順序(Collation)によって決定されます。
主要なCollationの特性は以下の通りです。
- utf8mb4_general_ci / utf8mb4_unicode_ci:
ci(case insensitive) の通り、大文字・小文字を区別しません。現代のアプリケーションでは、絵文字(4バイトUTF-8)をサポートするutf8mb4系のCollationが標準です。 - utf8mb4_bin: バイナリ比較を行うため、大文字・小文字を厳密に区別します(
Aとaは別物として扱われます)。パスワードハッシュや厳密な識別子の保存に適しています。 - latin1_swedish_ci: 過去のMySQLバージョンでのデフォルトでしたが、マルチバイト文字のサポートが限定的なため、現在は
utf8mb4系への移行が強く推奨されます。
lower_case_table_names はテーブル名とデータベース名にのみ作用し、カラム名には一切影響を与えない点に注意が必要です。