MySQL 5.7 升级至 8.0 存在四大不兼容变更:DATETIME 不支持 CURRENT_TIMESTAMP 默认值;JSON 虚拟列索引语法失效,须改用 JSON_VALUE();SHOW CREATE TABLE 输出含 5.7 特有注释导致导入失败;默认排序规则变为 utf8mb4_0900_ai_ci,引发隐式校对冲突。

CREATE TABLE 和 ALTER TABLE 在 MySQL 5.7 与 8.0 之间不是简单“语法微调”,而是存在几处**不兼容的硬性变更**,升级后直接执行旧 DDL 语句大概率报错。
DATETIME 默认值写法会直接报错
5.7 允许 DATETIME DEFAULT CURRENT_TIMESTAMP,但这是非标准扩展;8.0 严格拒绝该写法,报错 Invalid default value for 'ts'。
- 必须改用
TIMESTAMP类型(它原生支持CURRENT_TIMESTAMP) - 或显式写死默认值,如
DATETIME DEFAULT '1970-01-01 00:00:00' - 或放弃列级默认,改由应用层、触发器、或
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP(仅对TIMESTAMP有效)填充
JSON 虚拟列 + 索引语法不互通
5.7 常用 json_extract() 定义虚拟列再建索引;8.0 不认这种写法,且禁止在虚拟列上对 json_extract() 建索引。
- 5.7 写法:
ADD COLUMN name VARCHAR(100) AS (json_unquote(json_extract(data, '$.name'))) STORED - 8.0 正确写法:
CREATE INDEX idx_name ON t (JSON_VALUE(data, '$.name' RETURNING CHAR(100))) -
JSON_VALUE()必须带RETURNING明确类型,否则建索引失败 - 若保留旧虚拟列,需确保其表达式返回类型与索引字段完全一致(比如都为
CHAR(100))
SHOW CREATE TABLE 输出差异导致导入失败
5.7 的 mysqldump 输出常含 /!50100 ... / 注释或依赖旧 sql_mode(如 NO_FIELD_OPTIONS),8.0 解析时直接报错。
- 不要依赖
--compatible=5.7,它只改部分注释,不解决根本问题 - 稳妥做法:在 5.7 执行
SHOW CREATE TABLE t\G,人工删掉所有条件注释和冗余选项(如KEY_BLOCK_SIZE、STATS_PERSISTENT) - 升级前优先用
mysqlpump替代mysqldump,并加--skip-definer --skip-dump-rows验证结构可导入
字符集与排序规则变更引发隐式错误
8.0 默认 COLLATE utf8mb4_0900_ai_ci,而 5.7 多为 utf8mb4_general_ci。混合使用时,FIND_IN_SET()、CONCAT() 等函数可能抛出 Illegal mix of collations。
- 查当前列排序规则:
SHOW FULL COLUMNS FROM t - 统一改表:
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci - 临时绕过(仅调试):
FIND_IN_SET(CAST(A_CODE AS CHAR CHARACTER SET utf8mb4), @xxx),但不能作为长期方案


















