MySQL 8.0 从 5.7 迁过来的库,导入历史数据时报 Incorrect date value: '0000-00-00',导入中断在第三张表,sql_mode 里带着 STRICT_TRANS_TABLES,业务方坚持这些零日期不能改。

这类报错背后常见的原因有几处,逐个排除就行。MySQL 8 默认的 sql_mode 组合更严,零日期在严格模式下直接报错;严格模式打开后,超长和非法值不再降级成警告而是中断语句;导入会话的 sql_mode 被客户端的 init_command 又覆盖了一次;表的列定义是 NOT NULL 且默认零日期,严格模式下建表就过不去。

上来先看全局和会话两层的值

mysql -e "SELECT @@global.sql_mode, @@session.sql_mode\G"

随后导入前把会话放宽到兼容组合

mysql -e "SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION';"

接着用 init-command 跑一次导入

mysql --init-command="SET SESSION sql_mode=''" new_db < t_order.sql

等前面都确认过,再核对行数和零日期分布

mysql -e "SELECT COUNT(*) FROM new_db.t_order WHERE created_at='0000-00-00'"

恢复的判定其实很直接。导入全程没有 Incorrect date value 报错,行数与源库一致,零日期记录数能对上,业务查询恢复正常。

容易忽略的是,临时放宽 sql_mode 只适合一次性导入,导完必须恢复严格模式;零日期早晚要清洗,否则应用层的时间计算还是会踩到。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189