「本番(ステージング)サーバーは MariaDB 10.5系だが、ローカル開発環境は最新の MariaDB 11.8系を使いたい」——このギャップを埋めるための my.ini 設定と、既存データベースの直し方をまとめます。
MariaDB を 10.5 にダウングレードする必要はありません。11.8系のまま、10.5系が出すのと同じ挙動・同じスキーマになるよう設定で寄せるのがこの記事のゴールです。
1. なぜ問題になるのか
MariaDB は 10.5 → 11.8 の間に、いくつかのデフォルト値が静かに変わっています。バージョンが上がっただけなのに、ローカルで作った CREATE TABLE やダンプファイルが本番の 10.5 系に入らない、という事故が起きるのはこのためです。
| 環境 | MariaDB バージョン |
|---|---|
| ローカル開発(XAMPP等) | 11.8.8 |
| 本番 / ステージング | 10.5.x |
代表的な差分は次の4つです。
- 文字コード・照合順序(collation)のデフォルトが変わった
- TIMESTAMP列の暗黙デフォルトの挙動が変わった
sql_modeのデフォルトに含まれる項目が変わったutf8という名前が指すもの(utf8mb3扱いかutf8mb4扱いか)の解釈ルールが変わった
これらは「動かない」という派手な壊れ方より、「ダンプは通るが、リストアだけ失敗する」「文字化けしないのに絵文字だけ入らない」といった地味な壊れ方をするのが厄介なところです。
実際に起きた事故の例
ローカル(MariaDB 11.8)で WordPress サイトを作り、All-in-One WP Migration でエクスポートしたバックアップ(.wpress)を、本番のステージング(MariaDB 10.5.17)に復元しようとしたところ、復元が75%前後で止まりました。
原因は database.sql の中に
utf8mb3_uca1400_ai_ci
という照合順序が含まれていたことです。この uca1400 系の照合順序(Unicode Collation Algorithm 14.0.0 ベース)は MariaDB 10.10 以降にしか存在しないため、10.5 側では CREATE TABLE が「Unknown collation」で失敗し、wp_options や wp_posts などの標準テーブルごと作られませんでした。
犯人は「文字コードを何も指定しなかったこと」です。MariaDB 11.5以降は、utf8mb3 / utf8mb4 に照合順序を明示しない場合、UCA-14.0.0 系の照合順序を自動的に選ぶようになりました。これが 10.5 には存在しないため、環境をまたいだ瞬間に壊れます。
2. 差分ポイントの解説
2-1. 文字コード・照合順序(最重要)
MariaDB 11.5以降、CHARSET だけを指定して COLLATE を省略すると、UCA-14.0.0系の照合順序(*_uca1400_ai_ci)が自動的に選ばれます。
-- 11.5以降、COLLATEを省略すると…
CREATE TABLE t (c VARCHAR(10)) DEFAULT CHARSET=utf8mb4;
-- → 実際には utf8mb4_uca1400_ai_ci が採用される
この挙動を、10.5系が採用していたデフォルト(utf8mb4_general_ci)に固定するには character_set_collations システム変数を使います。これは MariaDB 11.5 で追加された変数で、文字コードごとに「COLLATE省略時のデフォルト照合順序」を明示的に上書きできます。
[mysqld]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci
character_set_collations = utf8mb3=utf8mb3_general_ci,utf8mb4=utf8mb4_general_ci,ucs2=ucs2_general_ci,utf16=utf16_general_ci,utf32=utf32_general_ci
補足: 本番側が
utf8mb4_general_ciではなくutf8mb4_unicode_ciを明示的に使っている場合は、上記のgeneral_ciをすべてunicode_ciに置き換えてください。大事なのは「10.5側が実際に何を使っているか」に合わせることで、general_ci自体に絶対的な正しさがあるわけではありません。本番サーバーで次のSQLを実行して確認しておくと確実です。SELECT @@character_set_server, @@collation_server;
2-2. utf8 の意味(utf8mb3 か utf8mb4 か)
MariaDB 10.6 以降、素の utf8 という名前は utf8mb4 のエイリアスではなく utf8mb3 のエイリアスとして扱われるのがデフォルトです(この点は MySQL 8 と異なり、MariaDB は今も utf8 = utf8mb3 側です)。ただし将来的な仕様変更や old_mode の設定次第で解釈が変わり得るため、明示的に固定しておくと安全です。
old_mode = UTF8_IS_UTF8MB3
2-3. TIMESTAMP列の暗黙デフォルト
MariaDB 10.10 で explicit_defaults_for_timestamp のデフォルトが 0(OFF) から 1(ON) に変わりました。この変数は、TIMESTAMP 型カラムを定義する際に DEFAULT / ON UPDATE を省略したときの自動補完の有無を切り替えます。
-- ts TIMESTAMP とだけ書いた場合
| explicit_defaults_for_timestamp | 実際に作られるカラム定義 |
|---|---|
0(10.5系のデフォルト) | timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() |
1(11.8系のデフォルト) | timestamp NULL DEFAULT NULL |
同じ CREATE TABLE 文を実行しても、生成される実スキーマが変わってしまうため、10.5側に合わせる場合は明示的に 0 へ戻します。
explicit_defaults_for_timestamp = 0
2-4. sql_mode の違い
sql_mode はバージョンごとにデフォルト値が地味に変化します。10.5系のデフォルトに合わせておくと、本番では通っていた INSERT / CREATE TABLE がローカルでだけ弾かれる、といった事故を防げます。
sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
特に注意したいのが NO_ZERO_DATE / NO_ZERO_IN_DATE です。これらが sql_mode に含まれていると、
datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
のような、WordPress をはじめ多くのアプリケーションが標準で使う「ゼロ日付」カラムの INSERT がエラーになります。10.5系のデフォルトにこの2つは含まれていないため、ローカルで独自に足していないか確認してください。
2-5. lower_case_table_names(設定では直せない差分)
Windows上のMariaDB(XAMPP等)は lower_case_table_names = 1(テーブル名を小文字に正規化)で動作しますが、Linux本番サーバーは通常 0(大文字小文字を区別)です。
この変数は稼働中のデータディレクトリに対して変更するとデータ破損につながるため、Windows側で無理に 0 に合わせることはできません。対策は設定ではなく運用ルール側で吸収します。
- テーブル名・データベース名は常に小文字で統一して命名する
- 大文字を含むテーブル名を作らない
3. my.ini 設定例(まとめ)
以上を踏まえた [mysqld] セクションの設定例です。既存の設定に追記・上書きしてください。
[mysqld]
# === MariaDB 10.5 互換設定 ===================================
# 本番/ステージングが MariaDB 10.5系のとき、11.8系のデフォルト値を
# 10.5系に合わせて固定し、スキーマ・ダンプの互換性を保つ。
# --- 文字コード / 照合順序 ---
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci
character_set_collations = utf8mb3=utf8mb3_general_ci,utf8mb4=utf8mb4_general_ci,ucs2=ucs2_general_ci,utf16=utf16_general_ci,utf32=utf32_general_ci
# utf8 を utf8mb3 のエイリアスとして扱う(10.5と同じ挙動)
old_mode = UTF8_IS_UTF8MB3
# --- TIMESTAMP列の暗黙デフォルト ---
explicit_defaults_for_timestamp = 0
# --- sql_mode ---
sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
# ===============================================================
設定変更後は MySQL(MariaDB) サービスを再起動します。XAMPP Control Panel であれば、
MySQL → Stop → Start
で反映されます。
反映されたかどうかの確認
再起動後、以下のSQLを実行して値を確認します。
SELECT
VERSION() AS mariadb_version,
@@character_set_server,
@@collation_server,
@@character_set_collations,
@@old_mode,
@@explicit_defaults_for_timestamp,
@@sql_mode;
character_set_collations に指定した内容と、他の値が想定通りになっていれば設定は反映されています。MariaDBやXAMPPをアップグレードするたびに、この確認クエリを流し直す習慣をつけておくと、デフォルト値の再変化に早く気づけます。
4. 設定変更だけでは直らない: 既存データベースの直し方
my.ini の変更が効くのは、設定変更後に新しく作られるデータベース・テーブルに対してだけです。すでに uca1400 系の照合順序で作られてしまった既存テーブルは、別途変換が必要です。
4-1. uca1400 を使っているテーブルを洗い出す
SELECT
TABLE_NAME,
TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_TYPE = 'BASE TABLE'
AND TABLE_COLLATION LIKE '%uca1400%'
ORDER BY TABLE_NAME;
カラム単位でも確認できます。
SELECT
TABLE_NAME,
COLUMN_NAME,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLLATION_NAME LIKE '%uca1400%'
ORDER BY TABLE_NAME, ORDINAL_POSITION;
4-2. データベース自体の既定値を直す
ALTER DATABASE 対象データベース名
CHARACTER SET utf8mb4
COLLATE utf8mb4_general_ci;
4-3. テーブルを一括変換する
対象が多い場合は、変換用SQLをまず生成してから実行するのが安全です。
SELECT CONCAT(
'ALTER TABLE ',
TABLE_NAME,
' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;'
) AS alter_sql
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_TYPE = 'BASE TABLE'
AND TABLE_COLLATION LIKE '%uca1400%'
ORDER BY TABLE_NAME;
生成された ALTER TABLE ... CONVERT TO CHARACTER SET ...; を目視確認してから実行します。
注意:
CONVERT TO CHARACTER SETはテーブルの既定値だけでなく、文字列型カラムの実データも変換対象になります。必ず事前にバックアップを取り、大量実行してエラーが出た場合は原因を確認してから続行してください。エラーを無視して進めるのは厳禁です。
4-4. 変換できたことを確認する
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_COLLATION LIKE '%uca1400%';
結果が0件になれば完了です。
5. 運用上の注意点
- 新しいデータベース/サイトを作った直後は、必ず照合順序を確認する。作り始めてから気づくと手戻りが大きくなります。
SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME; - 設定変更前には必ずバックアップを取る(データファイル、
my.ini本体の両方)。特に照合順序の一括変換は取り消しが難しい操作です。 - MariaDBやXAMPPをアップグレードした後は、この記事の確認クエリを再実行する。 バージョンアップのたびにデフォルト値が変わる可能性があるという前提で運用するのが安全です。
- ダンプ/リストアを伴う移行(バックアッププラグイン経由のエクスポートなど)を行う前に、生成された SQL に
uca1400のような新しいバージョン専用のキーワードが含まれていないかgrepで確認する一手間も有効です。grep -n -m 20 "uca1400" database.sql何も表示されなければ、少なくとも照合順序に関しては安全にリストアできる状態です。
6. まとめ
| 差分 | 10.5系の挙動 | 11.8系のデフォルト | 対処 |
|---|---|---|---|
| COLLATE省略時の照合順序 | *_general_ci(または明示指定値) | *_uca1400_ai_ci | character_set_collations で固定 |
utf8 の解釈 | utf8mb3 | utf8mb3(10.6以降は同じだが明示推奨) | old_mode = UTF8_IS_UTF8MB3 |
| TIMESTAMP列の暗黙デフォルト | 自動で NOT NULL DEFAULT current_timestamp() | NULL DEFAULT NULL | explicit_defaults_for_timestamp = 0 |
sql_mode | ゼロ日付を許容する構成が一般的 | バージョンにより変動 | 明示的に sql_mode を指定 |
lower_case_table_names | Linuxは0が多い | Windowsは1固定 | 設定では直せない。命名規則で吸収 |
MariaDB 11.8系はダウングレードせずに使い続けたまま、上記の設定を my.ini に入れておくだけで、「ローカルで作ったスキーマ・ダンプが本番の10.5系にそのまま入る」状態を維持できます。バージョンアップ自体を止める必要はなく、デフォルト値の差分だけをピンポイントで埋めればよい、というのがこの記事の要点です。
