MySQL时区错误源于系统、服务、客户端三层时区不一致,需分别检查并统一:修改my.cnf设置default-time-zone;加载时区表支持命名时区;应用连接时显式指定serverTimezone;DATETIME数据不自动转换,TIMESTAMP依赖时区转换,历史偏差需谨慎用DATE_ADD或CONVERT_TZ校正。
MySQL时区错误通常表现为查询结果中的时间比预期快或慢若干小时,比如存储的是 UTC 时间却按本地时区解析,或系统时区、MySQL 服务时区、客户端连接时区不一致。核心问题不是时间本身错了,而是“解释时间的规则”不统一。修复要从这三层入手。
MySQL 启动时会读取系统时区,但可能被配置文件覆盖。先确认当前生效的全局时区:
SELECT @@global.time_zone, @@session.time_zone;
若返回 SYSTEM,说明使用操作系统时区;若为具体值(如 '+08:00' 或 'Asia/Shanghai'),则以该值为准。不推荐长期用 SYSTEM,因为系统时区变更会影响数据库行为。
default-time-zone = '+08:00'
或更规范地使用命名时区(需确保 MySQL 时区表已加载):
default-time-zone = 'Asia/Shanghai'
重启 MySQL 生效。注意:修改后已有 DATETIME 字段不会自动转换,仅影响新写入和查询解释逻辑。
若想用 'Asia/Shanghai' 这类名称而非偏移量,必须初始化 MySQL 的时区表(mysql.time_zone* 系列表):
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Windows 不自带 zoneinfo,建议直接使用 '+08:00' 避免依赖。执行后可验证:
SELECT COUNT(*) FROM mysql.time_zone_name WHERE Name LIKE '%Shanghai%';
结果大于 0 表示加载成功。
即使服务器设为 '+08:00',如果应用连接时指定 serverTimezone=UTC(常见于 JDBC),时间仍会错乱。关键看连接参数:
mysqli_query($conn, "SET time_zone = '+08:00'");
--default-character-set=utf8mb4 --timezone='+08:00',或登录后执行 SET time_zone = '+08:00';
建议在应用层显式设置会话时区,不要依赖服务器默认值,尤其在跨时区部署时。
如果历史数据已按错误时区写入(例如本该存 UTC 却当东八区存了),不能简单改时区配置来“修正”。需分情况处理:
CONVERT_TZ() 校正关键字段(谨慎操作,先备份)例如将原按 UTC 存、实为北京时间的 DATETIME 字段批量校正(+8 小时):
UPDATE your_table SET created_at = DATE_ADD(created_at, INTERVAL 8 HOUR) WHERE ...;
务必在低峰期测试并备份。