CREATE TABLE时必须显式声明utf8mb4字符集及校对规则,因表级不自动继承server默认值;字段需单独指定CHARACTER SET utf8mb4,VARCHAR长度须适配索引限制(如≤191),并显式声明ENGINE=InnoDB、ROW_FORMAT=DYNAMIC及COMMENT。

CREATE TABLE 时必须显式声明 utf8mb4 字符集
MySQL 8.0 虽然默认 server 层字符集是 utf8mb4,但**表级字符集不会自动继承**——如果建表时不指定,可能沿用旧配置、或因存储引擎/模板行为导致意外回退。常见错误现象是:插入 emoji 或生僻中文后变成 ??? 或截断,而 SHOW CREATE TABLE 显示的却是 utf8mb4,实际字段级仍为 utf8(即 MySQL 的伪 utf8)。
实操建议:
- 建表语句中必须在末尾加上
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci(或utf8mb4_0900_ai_ci,MySQL 8.0 默认) - 不要依赖
DEFAULT CHARSET简写,它在某些客户端或驱动下解析不稳定 - 字段定义里也建议显式指定,例如:
name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
注意 VARCHAR 长度与索引限制的变化
从 utf8 切到 utf8mb4 后,单字符最大占用字节数从 3 升至 4,直接影响索引长度上限。InnoDB 默认单列索引前缀限制为 767 字节,这意味着:
VARCHAR(255) 在 utf8 下最多占 765 字节(255×3),可建索引;但在 utf8mb4 下理论最大占 1020 字节(255×4),会直接报错 Specified key was too long。
解决办法:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 将长文本字段索引控制在
VARCHAR(191)以内(191×4 = 764 字节) - 或启用大前缀支持:
SET GLOBAL innodb_large_prefix = ON(MySQL 5.7+ 默认开启,8.0 已强制启用) - 确保表使用
Barracuda文件格式:ROW_FORMAT=DYNAMIC或COMPRESSED
时间字段和默认值要匹配 MySQL 8.0 行为
MySQL 8.0 对 TIMESTAMP 和 DATETIME 的默认值校验更严格。若你沿用老写法:create_time DATETIME DEFAULT '0000-00-00 00:00:00',会触发 Invalid default value 错误。
正确做法:
- 用
CURRENT_TIMESTAMP替代字符串字面量:create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP - 如需自动更新,加
ON UPDATE CURRENT_TIMESTAMP - 避免
NOT NULL+ 空字符串默认值混用,尤其在utf8mb4下某些驱动对空值处理更敏感
别漏掉 ENGINE 和 COMMENT —— 它们影响可维护性
一张“规范”的 utf8mb4 表,光字符集对还不够。容易被忽略但关键的两点:
-
ENGINE=InnoDB必须显式写出。虽然 8.0 默认引擎已是 InnoDB,但某些迁移脚本或低权限账户下可能 fallback 到 MyISAM,后者对utf8mb4支持不完整 - 每个字段加
COMMENT,比如:status TINYINT NOT NULL DEFAULT 1 COMMENT '1=有效,0=逻辑删除'。这不是字符集问题,但一旦表变多、协作变复杂,没注释的utf8mb4表和没注释的乱码一样难 debug
最常被跳过的细节:建表后不验证。执行完 CREATE TABLE,立刻运行 SHOW CREATE TABLE ,逐行核对 your_table;CHARACTER SET、COLLATE、ENGINE、ROW_FORMAT 是否符合预期——尤其是生产环境,少一次验证,就多一次凌晨改库的风险。










