问题根源是时区解释规则不统一,需同步规范源库导出逻辑、mysql服务端时区、客户端连接时区三层配置;导出时须显式转换为utc字符串,禁用自动时区转换,迁移后统一改为datetime类型并校准时区。

直接结论:不是数据丢了,是解释规则乱了——必须统一源库导出逻辑、MySQL服务端时区、客户端连接时区三层规则,缺一不可。
导出前先确认源库时间字段的真实语义
异构库(如 PostgreSQL、Oracle、SQL Server)的时间类型没有 MySQL 的 TIMESTAMP 自动时区转换行为,导出时若不显式处理,极易把“本意是 UTC 存储”的值当成“本地时间字符串”直写进 MySQL,后续一查就偏 8 小时。
- 查清源库字段是否带时区(PostgreSQL 的
TIMESTAMPTZ、Oracle 的TIMESTAMP WITH TIME ZONE),导出时必须用AT TIME ZONE 'UTC'或等效方式强制转成 UTC 时间戳或 ISO 格式字符串 - SQL Server 的
DATETIME2默认无时区,但应用层可能按北京时间写入;导出时建议加CONVERT(VARCHAR, your_col, 126)得到带Z后缀的 UTC 字符串 - 避免用工具默认的“原样导出”:
pg_dump --inserts不处理时区,mysqldump导入时又按@@session.time_zone解释,两头错位
导入 MySQL 前必须重写时间值为显式 UTC 字符串
不要依赖 MySQL 的自动转换。哪怕你把 default-time-zone 设成 '+08:00',只要源数据本身是 UTC 字符串(如 '2026-09-30T12:00:00Z'),MySQL 仍会把它当本地时间再转一次,结果错上加错。
- 对所有时间字段,在 INSERT/LOAD DATA 语句中统一用
STR_TO_DATE(..., '%Y-%m-%dT%H:%i:%sZ')转成DATETIME,或用CONVERT_TZ(..., '+00:00', '+08:00')显式调整(前提是目标存的是北京时间语义) - 如果源数据是整数时间戳(秒级/毫秒级),导入前先除以 1000(毫秒→秒),再用
FROM_UNIXTIME(1727726400)转成DATETIME—— 它返回的是会话时区下的字面值,所以必须确保会话已设SET time_zone = '+08:00' - 严禁在 INSERT 中直接写
NOW()或CURRENT_TIMESTAMP替代源值;迁移脚本里所有时间字段都必须来自源数据,不能动态生成
MySQL 服务端与客户端时区必须硬绑定,且禁用 SYSTEM
哪怕数据导对了,只要 @@global.time_zone 是 SYSTEM,容器重启、系统时区更新、云平台调度都可能让时间突然跳变。
- 配置文件
/etc/my.cnf的[mysqld]段必须写死:default-time-zone = '+08:00'(别用Asia/Shanghai,除非你确认mysql.time_zone_name表已加载且不为空) - JDBC 连接串必须带
?serverTimezone=GMT%2B8&useTimezone=true;Spring Boot 用户注意:spring.jackson.time-zone对数据库层完全无效 - 命令行导入时,加参数
--default-character-set=utf8mb4 --timezone='+08:00';Navicat 等 GUI 工具需在连接设置里单独指定时区,不能只信服务器默认值
DATETIME 和 TIMESTAMP 混用是定时炸弹,迁移后立刻归一化
一张表里同时存在 DATETIME created_at 和 TIMESTAMP updated_at,在不同客户端下查出来的时间字面值可能完全不同——前者永远不变,后者随会话时区实时转换。
- 迁移完成后,用
SHOW CREATE TABLE扫一遍,把所有TIMESTAMP字段改成DATETIME(执行ALTER TABLE t MODIFY updated_at DATETIME) - 改完后,对原
TIMESTAMP字段跑一次修正:UPDATE t SET updated_at = CONVERT_TZ(updated_at, '+00:00', '+08:00')—— 前提是你确认旧值存的是 UTC - 如果历史数据语义模糊(比如不知道当初是按 UTC 还是北京时间存的),宁可全量导出再人工校验一行,也不要靠函数批量猜
最常被忽略的一点:迁移脚本里写的 SELECT NOW() 和应用代码里调的 new Date() 可能根本不在同一时区轨道上。修复必须覆盖从源库导出、中间传输、MySQL 存储、应用读取这四段链路,任何一段松动,时间就失准。











