错误源于MySQL 8.0+的utf8mb4_0900_as_cs排序规则与旧版SQL中CHARACTER SET utf8(utf8mb3)不兼容;应创建utf8mb4默认字符集库,并统一配置连接、ORM及客户端为utf8mb4。
MySQL 导入报错 ERROR 1253 (HY000):COLLATION 'utf8mb4_0900_as_cs' is not valid for CHARACTER SET 'utf8'
这是典型的字符集与排序规则不匹配问题,发生在用新版 mysql(8.0+)导入旧版(5.7 或更早)导出的 sql 文件时。mysqldump 在 8.0 默认用 utf8mb4_0900_as_cs,但老库建表语句里可能硬写了 character set utf8(即 utf8mb3),而该字符集不支持新排序规则。
- 别直接改 SQL 文件里的
COLLATE utf8mb4_0900_as_cs为COLLATE utf8mb3_general_ci——utf8mb3已被弃用,且无法存 emoji - 真正要做的,是让导入过程「忽略原建表语句中的字符集声明」,统一按目标库设定处理
- 导入命令加
--default-character-set=utf8mb4不够,它只影响客户端连接,不覆盖 CREATE TABLE 里的显式声明 - 安全做法是先创建空库并指定默认字符集:
CREATE DATABASE mydb DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci; - 再用
mysql --skip-column-names --default-character-set=utf8mb4 -D mydb ,关键在 <code>-D mydb强制使用目标库上下文
mysqldump 导出时就该避开 utf8mb4_0900_as_cs 排序规则
如果还能重新导出(比如你控制源库),就别等导入时报错再补救。8.0 默认的 utf8mb4_0900_as_cs 区分大小写和重音,但绝大多数业务不需要这么严格,反而容易和旧环境冲突。
- 导出时显式指定兼容性更强的排序规则:
mysqldump --default-character-set=utf8mb4 --skip-set-charset --collation-server=utf8mb4_unicode_ci ... -
--skip-set-charset很关键:它阻止 dump 文件开头写SET NAMES utf8mb4和SET collation_connection = ...,避免干扰目标库配置 - 如果源库是 5.7,建议直接用
--compatible=mysql40(虽略过部分语法,但能绕开所有 8.0 新特性) - 注意
--collation-server只影响连接层排序规则,真正生效的是建表语句中COLLATE子句——所以导出后仍需检查 SQL 文件是否含COLLATE utf8mb4_0900_as_cs,有就全局替换成utf8mb4_unicode_ci
ALTER TABLE 批量修正已导入表的字符集混乱
如果已经导入完成,但发现部分表用了 utf8 字符集或 latin1,字段存中文变问号,不能只改表默认字符集——字段级定义才是实际生效点。
- 查出问题表:
SELECT table_name, table_collation FROM information_schema.tables WHERE table_schema = 'mydb' AND table_collation LIKE 'utf8%'; - 逐字段确认编码:
SELECT column_name, character_set_name, collation_name FROM information_schema.columns WHERE table_schema = 'mydb' AND table_name = 't1' AND character_set_name IS NOT NULL; - 改字段字符集(保留数据不乱码):
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;—— 这条会重写所有文本字段,但不会损坏已有 UTF-8 数据 - 别用
MODIFY COLUMN单独改某个字段,容易漏掉其他字段,也容易因长度计算差异触发Row size too large - 执行前务必备份,
CONVERT TO在大表上会锁表(8.0 中可加ALGORITHM=INPLACE降低影响,但需满足条件)
PHP 连接 MySQL 8.0 时触发 ERROR 1253 的隐藏路径
不是只有 SQL 导入才碰这个错。当 PHP 应用用 mysqli 或 PDO 连接 8.0 数据库,并执行含字符集声明的查询(比如带 COLLATE 的 ORDER BY),也可能收到同错——本质是客户端声明的字符集和服务器期望不一致。
- 检查 PHP 连接串是否含
;charset=utf8:必须改为;charset=utf8mb4,否则 MySQL 认为客户端只支持utf8mb3 - PDO 构造时别只设
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8",要写全:"SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci" - mysqli_connect() 后立刻调用
mysqli_set_charset($conn, 'utf8mb4'),比在 DSN 里写更可靠 - 若用 Laravel,确认
config/database.php中mysql配置的'charset'和'collation'均为utf8mb4系,且'prefix'后没拼错字符集名
字符集升级不是改个配置就能完事的事,真正麻烦的是那些散落在建表语句、连接参数、ORM 配置、甚至前端 JS 字符串拼接里的隐式依赖——它们不会报错,只会某天突然让一个 emoji 显示成 。










