MySQL 8.0 必须移除 NO_AUTO_CREATE_USER,因其已被彻底删除,配置或 SQL 中存在该值将导致启动失败;需清理 my.cnf、备份 SQL 及应用层连接初始化中的相关设置。

直接删掉 NO_AUTO_CREATE_USER,否则 MySQL 8.0 启动就失败——这是最常卡住升级的第一道墙。
为什么NO_AUTO_CREATE_USER必须被移除
MySQL 8.0 彻底移除了这个选项,不是“不推荐”,而是硬性拒绝。只要配置文件、备份 SQL 或客户端连接时显式设置了它,mysqld 就会报错退出,典型错误是:Variable 'sql_mode' can't be set to the value of 'NO_AUTO_CREATE_USER'。这不是警告,是启动失败。
- 5.7 的默认
sql_mode包含它;8.0 的默认值里已剔除 - 很多 ORM(如老版 Laravel、Django MySQL backend)或框架初始化脚本会自动设置全量 5.7 模式,连带把这行也发过去
- 即使你没手动配,
mysqldump导出的 SQL 文件里也可能带SET sql_mode = '...'语句,里面藏着它
导入前必须清理备份 SQL 中的非法模式
用 mysqldump 做逻辑迁移时,不能直接 dump → source。导出的 SQL 很可能含 5.7 特有模式,必须预处理:
- 导出时加
--skip-definer和--set-gtid-purged=OFF,但还不够——sql_mode是独立写入的 - 导出后立刻检查:
grep -n "NO_AUTO_CREATE_USER\|DB2\|ORACLE\|POSTGRESQL" backup.sql - 找到就删掉整段
SET sql_mode = '...'行,或手动替换为兼容值,例如:SET sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; - 别信
--compatible=mysql40:它只改语法输出,不清理已存在的非法模式
新实例启动后如何安全设值
不要依赖配置文件一劳永逸。8.0 启动时若读到含 NO_AUTO_CREATE_USER 的 my.cnf,照样失败。正确做法是分两步:
- 先确保
my.cnf中的sql_mode配置项里不含任何已移除项(尤其检查注释里是否残留) - 导入数据前,在空的新 8.0 实例中手动执行:
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; - 再执行
source backup.sql—— 这样导入过程不会因模式冲突中断 - 导入完成后,用
SELECT @@sql_mode;确认生效,注意:该设置只对新连接有效,已有连接需重连
真正容易被忽略的是:应用层代码或中间件(比如某些 PHP 框架的 DB 初始化逻辑)可能在每次连接建立时主动执行 SET sql_mode。这类行为不会出现在备份 SQL 里,也不会被 mysql_upgrade 扫描到,只能靠开启 general_log 抓包定位。升级后如果偶发报错,先看日志里第一条执行的语句是不是又偷偷塞回了 NO_AUTO_CREATE_USER。


















