从MySQL 5.7(Ubuntu 16.04)迁移至MySQL 8.0(Ubuntu 20.04)时导入备份文件出现无效日期时间值错误的解决咨询
解决MySQL 8.0导入夏令时无效timestamp数据的问题
我之前也碰到过一模一样的夏令时时间导入坑——MySQL 8.0在时间合法性校验上确实比5.7严格太多,尤其是这种夏令时跳变产生的「压根不存在的时间点」(比如欧洲CEST时区3月最后一个周日的2:00-3:00,时钟直接从2点跳到3点,这个区间的时间实际是不存在的),5.7会宽松允许存储,但8.0默认的严格模式直接就会抛出1292错误卡住导入。
下面是几个可行的解决办法,按操作复杂度从低到高排序:
方法一:临时调整SQL模式,跳过严格校验
这是最快速的临时解决方案,适合紧急导入场景:
- 登录新服务器的MySQL 8.0:
mysql -u username -p - 临时修改当前会话的SQL模式,关闭时间相关的严格校验:
要是还是报错,也可以彻底关闭所有严格校验(注意:导入完成后一定要改回默认,避免后续数据写入出现不规范问题):SET sql_mode = 'NO_ENGINE_SUBSTITUTION';SET sql_mode = ''; - 执行导入命令(假设你的备份压缩包是
backup.sql.gz):zcat backup.sql.gz | mysql -u username -p your_database_name - 导入完成后,记得把SQL模式改回MySQL 8.0的默认值:
SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
方法二:从源端重新导出时处理时区,避免夏令时冲突
如果可以重新导出备份,推荐从MySQL 5.7端调整时区参数,让时间以UTC格式导出,这样导入到8.0时就不会有夏令时冲突:
执行mysqldump时加上--skip-tz-utc参数,强制以UTC时间写入备份文件:
mysqldump -u username -p --skip-tz-utc --default-character-set=utf8mb4 your_database_name | gzip > backup_utc.sql.gz
这个操作会让导出的timestamp数据脱离服务器本地时区,以UTC时间的形式存储,导入到新服务器时,MySQL会自动根据当前时区转换,完美避开夏令时的无效时间点。
方法三:临时修改表结构,用datetime中转导入
如果前两种方法都不适用,可以先把目标库的timestamp字段临时改成datetime,导入后再改回:
- 在MySQL 8.0中,修改涉及的表结构:
ALTER TABLE your_table MODIFY COLUMN timestamp datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; - 执行导入命令——datetime类型不会校验时间是否符合夏令时规则,会直接存储原始时间字符串。
- 导入完成后,再把字段改回timestamp:
小贴士:只要新旧服务器的时区一致,这个转换过程不会出现数据误差,MySQL会自动处理时区映射。ALTER TABLE your_table MODIFY COLUMN timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
最后补充个小检查:虽然你说新旧服务器系统时区都是CEST,但可以用SELECT @@global.time_zone, @@session.time_zone;确认MySQL的全局/会话时区是否都是SYSTEM(跟随系统时区),避免隐性的时区差异问题。
内容的提问来源于stack exchange,提问作者merlin




