What to Check When Migrating from utf8mb3 to utf8mb4 in Aurora MySQL
公開日 2026-08-13 · 更新日 2026-08-13 · 最終検証日 2026-08-13
結論
When migrating from utf8mb3 (`utf8` is an alias for this in MySQL 5.7) to utf8mb4, first check three things: (1) the index key length limit, (2) collation selection, and (3) the server parameters and the connection's character set. Key length is the particular problem: since utf8mb4 uses up to 4 bytes per character, a standalone index on `VARCHAR(255)` requires 1020 bytes, and `ALTER TABLE` fails in an environment with a 767-byte limit. Since conversion involves recreating the table, treat it as a planned operation.
この文書の適用条件
| 対象製品 | Aurora MySQL (MySQL-compatible edition) / MySQL |
|---|---|
| 確認バージョン | Aurora MySQL 2.x (MySQL 5.7-compatible) / 3.x (MySQL 8.0-compatible). `utf8mb4_0900_ai_ci` is available only on 3.x (MySQL 8.0-compatible) |
| 適用環境 | Amazon Aurora, Amazon RDS for MySQL, on-premises MySQL |
| 必要権限 | Investigation requires read access to `information_schema`. Conversion requires `ALTER` on the target table; parameter changes require IAM privileges such as `rds:ModifyDBClusterParameterGroup` |
| 実行影響 | No impact from the investigation SQL. `CONVERT TO CHARACTER SET` involves recreating the table (copying data) |
| 再起動 | Not required for table conversion. How a server parameter is applied differs per parameter, so check `ApplyType` |
| 最終検証日 | 2026-08-13 |
そのまま実行できるコマンド
- 対象
- Aurora MySQL 2.x / 3.x, MySQL 5.7 / 8.0
- 権限
- Connection privilege (read global variables)
- 変更作業
- None (read-only)
- Production実行
- Possible
-- 対象: Aurora MySQL 2.x / 3.x、MySQL 5.7 / 8.0
-- 権限: 接続権限(グローバル変数の参照のみ)
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
'character_set_server',
'character_set_database',
'character_set_client',
'character_set_connection',
'character_set_results',
'collation_server',
'collation_database',
'collation_connection'
);In MySQL 5.7, `utf8` is an alias for `utf8mb3`. Even if this shows `utf8`, understand that it is actually utf8mb3 with a 3-byte limit. In MySQL 8.0, using `utf8` as an alias is deprecated.
- 対象
- Aurora MySQL 2.x / 3.x, MySQL 5.7 / 8.0
- 権限
- Read access to `information_schema` (subject to metadata visibility rules)
- 変更作業
- None (read-only)
- Production実行
- Possible
-- 対象: Aurora MySQL 2.x / 3.x、MySQL 5.7 / 8.0
-- 権限: information_schema の参照権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
TABLE_SCHEMA,
TABLE_NAME,
ENGINE,
ROW_FORMAT,
TABLE_COLLATION,
ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 1) AS size_mb
FROM information_schema.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND (TABLE_COLLATION IS NULL OR TABLE_COLLATION NOT LIKE 'utf8mb4%')
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;Sorted by `size_mb` descending. Since conversion is a table-by-table data copy, this order is also the order of how heavy each migration step will be.
- 対象
- Aurora MySQL 2.x / 3.x, MySQL 5.7 / 8.0
- 権限
- Read access to `information_schema`
- 変更作業
- None (read-only)
- Production実行
- Possible
-- 対象: Aurora MySQL 2.x / 3.x、MySQL 5.7 / 8.0
-- 権限: information_schema の参照権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH AS max_chars,
CHARACTER_OCTET_LENGTH AS max_bytes,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND CHARACTER_SET_NAME IS NOT NULL
AND CHARACTER_SET_NAME <> 'utf8mb4'
ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION;Even if the table default is utf8mb4, an individual column may still have an explicit character set left over. A table-level check alone can miss this, so always check at the column level as well.
- 対象
- Aurora MySQL 2.x / 3.x, MySQL 5.7 / 8.0 (InnoDB)
- 権限
- Read access to `information_schema`
- 変更作業
- None (read-only)
- Production実行
- Possible
-- 対象: Aurora MySQL 2.x / 3.x、MySQL 5.7 / 8.0(InnoDB)
-- 権限: information_schema の参照権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
-- utf8mb4 は 1 文字最大 4 バイト。プレフィックス長指定の無い文字列列だけを対象に、
-- 変換後に必要となるキー長(バイト)を見積もる。
SELECT
s.TABLE_SCHEMA,
s.TABLE_NAME,
s.INDEX_NAME,
GROUP_CONCAT(s.COLUMN_NAME ORDER BY s.SEQ_IN_INDEX) AS index_columns,
SUM(c.CHARACTER_MAXIMUM_LENGTH * 4) AS bytes_after_utf8mb4
FROM information_schema.STATISTICS s
JOIN information_schema.COLUMNS c
ON c.TABLE_SCHEMA = s.TABLE_SCHEMA
AND c.TABLE_NAME = s.TABLE_NAME
AND c.COLUMN_NAME = s.COLUMN_NAME
WHERE s.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND c.CHARACTER_MAXIMUM_LENGTH IS NOT NULL
AND s.SUB_PART IS NULL
GROUP BY s.TABLE_SCHEMA, s.TABLE_NAME, s.INDEX_NAME
HAVING bytes_after_utf8mb4 > 767
ORDER BY bytes_after_utf8mb4 DESC;First list everything over 767 bytes, then judge against your own environment's limit. In an environment where the row format is `DYNAMIC` or `COMPRESSED` and the 3072-byte limit applies, change the `HAVING` threshold to 3072 to narrow it down. A standalone index on `VARCHAR(255)` becomes 255 × 4 = 1020 bytes, which will always fail in an environment with the 767-byte limit.
- 対象
- Aurora MySQL 2.x / 3.x, MySQL 5.7 / 8.0
- 権限
- `ALTER` on the target table
- 変更作業
- Yes (table recreation and data copy)
- Production実行
- Not possible for large tables. Carry out as a planned operation
-- 対象: Aurora MySQL 2.x / 3.x、MySQL 5.7 / 8.0
-- 権限: 対象テーブルへの ALTER 権限
-- 変更作業: あり(テーブル作り直し + 全行のデータコピー)
-- Production 実行: 大きなテーブルでは不可。所要時間を実測してから計画実行する
-- 1) 変換前に現在の定義を保存しておく(切り戻し判断の材料になる)
SHOW CREATE TABLE SampleDB.sample_table;
-- 2) テーブル既定と全文字列列をまとめて変換する
ALTER TABLE SampleDB.sample_table
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
ALGORITHM = COPY,
LOCK = SHARED;
-- 3) 変換結果を確認する
SELECT COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'SampleDB'
AND TABLE_NAME = 'sample_table'
AND CHARACTER_SET_NAME IS NOT NULL;`CONVERT TO CHARACTER SET` recreates the table, so it cannot be run as an online DDL (`ALGORITHM=INPLACE`). `LOCK=SHARED` allows reads but blocks writes. For a large table where writes cannot be blocked, an online schema-change tool such as `pt-online-schema-change` or `gh-ost` is an option. Since duration varies greatly by table size, instance class, and concurrent load, always measure it against production-equivalent data (this article does not give a duration estimate).
- 対象
- Aurora MySQL 2.x / 3.x, MySQL 5.7 / 8.0 (per-session)
- 権限
- Connection privilege
- 変更作業
- Yes (only the current session's character set setting)
- Production実行
- Possible (self-contained within the session)
-- 対象: Aurora MySQL 2.x / 3.x、MySQL 5.7 / 8.0(セッション単位の設定)
-- 権限: 接続権限
-- 変更作業: あり(現在のセッションのみ。他セッションには影響しない)
-- Production 実行: 可能
-- クライアント・接続・結果の3つの文字セットをまとめて切り替える
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 現在のセッションの値を確認する
SHOW SESSION VARIABLES WHERE Variable_name IN (
'character_set_client',
'character_set_connection',
'character_set_results',
'collation_connection'
);Even if the table is utf8mb4, if the connection stays utf8mb3, 4-byte characters will either be dropped on save or cause an error. JDBC, PDO, and drivers for various languages also have a connection character set setting, so check the application's connection string as well.
- 対象
- Aurora MySQL (DB cluster parameter group)
- 権限
- IAM: `rds:DescribeDBClusterParameters`, `rds:ModifyDBClusterParameterGroup`
- 変更作業
- Yes (changes a parameter that affects the whole cluster)
- Production実行
- Carry out only after going through change management. Check how each parameter is applied
# 対象: Aurora MySQL(DBクラスターパラメータグループ)
# 権限: IAM rds:DescribeDBClusterParameters, rds:ModifyDBClusterParameterGroup
# 変更作業: あり(クラスター全体に効くパラメータ変更)
# Production 実行: 変更管理を通したうえで実施
# 1) まず現在値と反映方法(ApplyType)を確認する。static なら再起動が必要になる
aws rds describe-db-cluster-parameters \
--db-cluster-parameter-group-name example-aurora-mysql-cluster-params \
--query "Parameters[?starts_with(ParameterName, 'character_set') || starts_with(ParameterName, 'collation')].{Name:ParameterName,Value:ParameterValue,Apply:ApplyType}" \
--output table
# 2) 既定の文字セットと照合順序を変更する
aws rds modify-db-cluster-parameter-group \
--db-cluster-parameter-group-name example-aurora-mysql-cluster-params \
--parameters '[
{"ParameterName":"character_set_server","ParameterValue":"utf8mb4","ApplyMethod":"pending-reboot"},
{"ParameterName":"collation_server","ParameterValue":"utf8mb4_unicode_ci","ApplyMethod":"pending-reboot"}
]'Changing the server parameters only affects "the default for objects created from now on" and "the default for connections without an explicit setting" — it does not change the character set of existing tables. Converting existing data requires `ALTER TABLE`. Match `ApplyMethod` to the `ApplyType` checked in step 1 above (specifying `immediate` for a `static` parameter causes an error).
結果の読み方
| 列 | 意味 | 確認するポイント |
|---|---|---|
| TABLE_SCHEMA / TABLE_NAME | Target schema and table | Whether this is narrowed down to the schema the application actually uses |
| INDEX_NAME | Index name | The available options differ depending on whether it is the primary key or a secondary index |
| index_columns | Columns making up the index | For a composite index, the sum of all column byte lengths hits the limit |
| bytes_after_utf8mb4 | Estimated key length required after converting to utf8mb4 (bytes) | Over 767 fails in an environment with the old limit; over 3072 fails regardless of the setting |
| ROW_FORMAT | InnoDB's row format | Whether it is `DYNAMIC` / `COMPRESSED` changes how the key length limit is judged |
| TABLE_COLLATION | The table's default collation | Whether it is in the utf8mb4 family. Also check per-column settings separately |
| CHARACTER_OCTET_LENGTH | Maximum byte count under the current character set | 3x for utf8mb3, 4x for utf8mb4. Used to estimate the row size limit |
| size_mb | Approximate size of data plus indexes | The order of how heavy the conversion work is; larger ones need measurement beforehand |
こういう状況で使います
- Saving an emoji or certain kanji causes an `Incorrect string value` error
- Saving succeeds, but the emoji comes back as `????` or an empty string
- `ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4` fails with `Specified key was too long`
- The table is utf8mb4, but the application still shows garbled text
- Comparing the same strings gives a different result before and after the conversion (duplicate errors increased or decreased)
考えられる原因(可能性の高い順)
01
utf8 (utf8mb3) can only store up to 3 bytes
In MySQL 5.7, `utf8` is an alias for `utf8mb3`, which uses at most 3 bytes per character. Emoji and some extended CJK kanji require 4 bytes, so they cannot be stored.
02
Hitting the index key length limit
InnoDB index keys have a limit: 767 bytes with the legacy setting (`innodb_large_prefix` disabled, `COMPACT` / `REDUNDANT` row format), or 3072 bytes with `DYNAMIC` / `COMPRESSED`. Since utf8mb4 counts 4 bytes per character, a standalone index on `VARCHAR(255)` requires 1020 bytes and fails under the 767-byte limit.
03
The connection-side character set doesn't match
Even if the table is utf8mb4, if the connection is utf8mb3, 4-byte characters are dropped before reaching the server. Check the driver's connection string or the `SET NAMES` setting.
04
A column-level override remains
Changing the table default does not change a column that has an explicit character set specified. Checking at the column level is necessary.
05
A collation difference changed comparison results
`utf8mb4_general_ci` and `utf8mb4_unicode_ci` differ in which characters they consider equivalent. Changing collation can change which set of rows trips a unique constraint.
確認手順
- 1
Check the current value across all four levels: server, database, table, and column
参照のみA higher-level setting is only a default — an explicit setting at a lower level wins. Check all four levels with read-only SQL.
- 2
List tables and columns that are not utf8mb4
参照のみDetermine the targets using `information_schema.TABLES` and `information_schema.COLUMNS`.
- 3
Find indexes that will hit the key length limit
参照のみAlways do this before running the conversion. A table that shows up here needs its index definitions reviewed before conversion.
- 4
Check the row format and the state of `innodb_large_prefix`
参照のみOn a MySQL 5.7-compatible environment, check with `SELECT @@global.innodb_large_prefix, @@global.innodb_default_row_format;`. `innodb_large_prefix` has been removed in MySQL 8.0.
- 5
Convert one table in a test environment and measure the time and result
中Measure with a data volume equivalent to production. The time obtained here is the only real basis for planning.
- 6
Check the difference in comparison results caused by the collation change
中In a test environment, check whether duplicates occur after conversion on columns with a unique constraint.
対応方法
すぐに実施できる低リスクの対応
Align the connection side to utf8mb4
低Set the application's connection character set to `utf8mb4`. Doing this before the table conversion means things are handled correctly right after the conversion.
Finalize the scope and size
参照のみTurn the output of the discovery SQL into a work list. The schedule cannot be set until the number and size of tables are known.
事前検討が必要な変更
Address indexes that exceed the key length first
高Choose one of: shortening the column length (e.g., `VARCHAR(255)` → `VARCHAR(191)`), specifying a prefix length, or redesigning the index itself. All of these are schema changes.
Standardize the row format to `DYNAMIC`
高This enables use of the 3072-byte limit. On a MySQL 5.7-compatible environment, this needs to be checked together with enabling `innodb_large_prefix`. It involves recreating the table.
Decide on a collation and standardize it across all tables
中If collations differ per table, joins produce collation-mismatch errors. Standardize it during migration.
再起動・サービス影響を伴う変更
Run `ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4`
高Since it recreates the table, this takes a long time on large tables and blocks writes for that duration. Plan the duration based on measured values.
Convert using an online schema-change tool
高Using `pt-online-schema-change` or `gh-ost` allows conversion without stopping writes, but it consumes extra storage for the copy table and requires verifying interactions with replication and triggers beforehand.
Reload into a new cluster and cut over
専門家レビュー必須When there are many tables, it can be more reliable to load data into a new utf8mb4 environment and cut over. See the migration planning article for cutover planning.
!注意事項
- `CONVERT TO CHARACTER SET` recreates the table. It requires time and storage proportional to table size, plus a write stop. This is not an operation that finishes without downtime.
- Conversion increases the maximum byte count of a column, which can newly hit the row size limit or the index key length limit. Do not run it without checking beforehand.
- Changing the collation changes the result of string comparison and sorting. On columns with a unique constraint, this can produce duplicate errors after conversion.
- Changing the server parameters alone does not change existing tables. Conversely, changing only the table while the connection side stays utf8mb3 still drops characters. Align both.
- If data containing 4-byte characters already failed to be inserted into a utf8mb3 column, the lost data is not recovered by the conversion. Check the application-side error log first.
- This article does not provide a duration estimate. Since it varies greatly by table size, instance class, and concurrent load, always use a value measured in a test environment.
バージョン・環境による違い
これで解決しない場合に確認すること
Check the application's driver settings
Check whether JDBC's `characterEncoding`, PHP's `charset`, and the defaults of each language's client library are set to `utf8mb4`.
Check whether the collation matches across tables being joined
Joining columns with different collations can cause runtime errors or prevent index usage.
Check the character set of stored procedures, views, and triggers
A routine retains the character set from when it was created. It may need to be recreated after the table conversion.
Check whether replicas or DMS targets are converted at the same time
Converting only the source causes inconsistency or apply errors on the replication target.
Check whether the character set is preserved in the backup restore procedure
Confirm beforehand that you can roll back to the pre-conversion definition.
この文書の根拠と限界
製品の公式ドキュメントに基づく説明
Based on the public specifications of MySQL character sets and collations (`utf8mb3` / `utf8mb4`, `utf8mb4_general_ci` / `utf8mb4_unicode_ci` / `utf8mb4_0900_ai_ci`), InnoDB's index key length limit and row formats, `ALTER TABLE ... CONVERT TO CHARACTER SET`, and Amazon Aurora's cluster parameter groups. Conversion duration is not stated because it is environment-dependent.
よくある質問
What's the difference between utf8 and utf8mb4?
In MySQL 5.7, `utf8` is an alias for `utf8mb3`, which can only store up to 3 bytes per character. Emoji and some extended CJK kanji need 4 bytes, so they cannot be stored unless the column is `utf8mb4`. In MySQL 8.0, using `utf8` as an alias is deprecated.
Can this be run in production?
All the discovery SQL is read-only and can be run in production. `ALTER TABLE ... CONVERT TO CHARACTER SET` involves recreating the table and blocks writes during that time, so depending on scale, use a planned outage or an online schema-change tool.
Why does ALTER TABLE fail with "key too long"?
Because utf8mb4 counts 4 bytes per character, which increases the index key length. A standalone index on `VARCHAR(255)` becomes 1020 bytes and always fails in an environment with the 767-byte limit. First do one of: shortening the column length, specifying a prefix length, or reviewing the row format.
Which collation should I choose?
It depends on whether you want to avoid changing existing comparison results. `utf8mb4_general_ci` and `utf8mb4_unicode_ci` differ in which characters they consider equivalent, and a column with a unique constraint can change which rows are considered duplicates. `utf8mb4_0900_ai_ci` is available only on a MySQL 8.0-compatible environment. Decide after checking for duplicates using real data in a test environment.
What permissions are required?
Read access to `information_schema` is enough for the investigation SQL (subject to metadata visibility rules, so objects you don't have privileges on won't appear in the results). Conversion requires `ALTER` on the target table, and changing the parameter group requires IAM privileges.
If I set the server parameters to utf8mb4, do existing tables change too?
No. The parameters only affect objects created from now on and the default for connections without an explicit setting. Existing data requires an `ALTER TABLE` per table.
この文書がカバーする質問
- Saving an emoji in MySQL causes Incorrect string value
- Index creation fails after converting to utf8mb4
- Should I use utf8 or utf8mb4
- Want to change the default character set of Aurora MySQL to utf8mb4
リスク表示の意味
- 参照のみデータと設定を変更しません。
- 低影響は限定的ですが、権限と負荷の確認が必要です。
- 中性能・ロック・コストに影響する可能性があります。
- 高障害・データ損失・復旧作業が発生する可能性があります。
- 専門家レビュー必須本番適用前に別途レビューが必須です。
GIIPの対応範囲
Character set migration looks like a "do it once and you're done" task, but in practice the settings keep drifting after migration every time a column is added or a table is newly created. GIIP periodically runs the utf8mb4-target discovery SQL to continuously check whether any new non-utf8mb4 columns have appeared. It only notifies when a difference shows up, leaving the decision on whether to make a schema change to a human, which prevents settings from reverting after the migration is done.
執筆・技術検証
GIIP プロダクション運用チーム
大規模Webサービス、SQL Server、Oracle、AWS、Azureの設計・移行・運用に約30年従事。x12largeクラスのAWS RDS for SQL Server環境12セット、約12万テーブルのOracle環境、約3TBのTiDBからAurora MySQLへの移行を経験。現在も複数のクラウドデータベースと約30のWebサービスを、AIエージェントと人間の専門家が継続的に監視・運用しています。
How to Investigate a Slow Query in Aurora MySQL
A procedure for finding slow queries by starting with lower-risk checks, in the order: slow query log, PROCESSLIST, EXPLAIN, and digest aggregation. Also shows alternatives for environments where performance_schema is disabled.
database-migrationHow to Plan a 3TB-Scale Database Migration
A 3TB-class migration plan is built in this order: measure actual size, choose a cutover method, measure duration with a trial run, and design verification and rollback. This is a procedure for setting the schedule from measured values rather than rule-of-thumb figures.
tidbChecklist for Migrating from TiDB to Aurora MySQL
TiDB is MySQL-compatible, but not identical. This organizes the differences in primary keys, ID generation, transactions, statistics, and capacity into a pre-migration checklist with verification SQL.
aurora-mysqlWhy AWS DMS Reports Error 1032 and How to Investigate It
Error 1032 in DMS CDC means the corresponding row doesn't exist on the target. This organizes how to read the control tables, how to check for primary key mismatches, and the available task-setting options.
関連サービス
Get help setting up a test environment for character set conversion
同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。
Get help setting up a test environment for character set conversion