必须同时修改配置文件和执行ALTER TABLE CONVERT TO CHARACTER SET,因为仅ALTER DATABASE只改数据库默认字符集,不改变已有表及字段的字符集定义,字段仍按utf8(utf8mb3)解析4字节Emoji导致报错。
直接改配置文件 + 批量执行 ALTER DATABASE 和 ALTER TABLE ... CONVERT TO CHARACTER SET,缺一不可。只改服务端或只改表,Emoji 插入仍会报 Incorrect string value 错误。
该语句只改数据库默认字符集,不影响已有表和字段的实际定义。表结构里仍保留 utf8(即 utf8mb3)声明,MySQL 读写时仍按 3 字节解析,遇到 4 字节 Emoji 就截断或报错。
SHOW CREATE TABLE table_name 查看建表语句,如果字段定义里还写着 CHARACTER SET utf8,说明没生效character_set_database 是 utf8mb4,只要表字段自己声明了 utf8,就优先用字段级设置VARCHAR(255) 且未开启 innodb_large_prefix,直接 CONVERT 可能失败,需先调大 innodb_file_format
MySQL 连接行为由客户端、命令行工具、服务端三处配置共同决定。只在 [mysqld] 段设 character-set-server = utf8mb4,mysql 命令行连上去后 character_set_client 仍是 utf8。
[mysqld]:加 character-set-server = utf8mb4 和 collation-server = utf8mb4_0900_ai_ci(MySQL 8.0 推荐,别用 utf8mb4_unicode_ci)[client]:加 default-character-set = utf8mb4(影响 mysqldump、mysqladmin 等所有客户端工具)[mysql]:加 default-character-set = utf8mb4(专用于 mysql 命令行客户端自身)my.cnf 必须挂载到 /etc/mysql/my.cnf,权限设为 644,否则 MySQL 静默跳过加载手动一条条写 ALTER TABLE 不现实。用 information_schema 生成语句最稳,但要注意排序规则一致性。
SELECT CONCAT('ALTER TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;') AS stmt FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db_name';
SET SESSION innodb_file_per_table = ON; SET SESSION innodb_file_format = Barracuda;
SHOW CREATE TABLE your_table,确认字段定义里已变成 utf8mb4
最容易被忽略的是应用连接参数——哪怕数据库全配好了,PHP 的 mysqli 或 PDO 还得显式指定 charset=utf8mb4,否则连接初始化时仍用默认 utf8。这点在宝塔或 Docker 环境里尤其容易漏掉。