mysql_tzinfo_to_sql执行后时区表为空的根源是输出未导入mysql库、系统缺tzdata包或未重启mysqld服务,须严格验证select count(*) from mysql.time_zone_name where name='asia/shanghai'返回1且重启生效。

mysql_tzinfo_to_sql 命令执行后无报错但时区表仍为空
常见现象是命令跑完了,mysql.time_zone_name 里查不到 Asia/Shanghai,甚至 SELECT COUNT(*) FROM mysql.time_zone_name; 返回 0。根本原因不是命令没运行,而是输出没进对库,或权限/路径不对。
- 确认命令末尾指定了
mysql数据库:正确写法是mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql(注意最后的mysql是数据库名,不是用户名) - 检查系统是否真有时区文件:运行
ls -d /usr/share/zoneinfo/Asia/Shanghai,若提示“没有那个文件或目录”,说明操作系统未安装tzdata包(CentOS/RHEL 用yum install tzdata,Ubuntu/Debian 用apt install tzdata) - 避免用 sudo 执行管道前半段:如
sudo mysql_tzinfo_to_sql ... | mysql -u root -p mysql,会导致权限上下文不一致,root 密码可能被拒绝;应统一用 root 用户执行整条命令
导入后 SELECT ... LIKE '%Shanghai%' 仍无结果
即使命令成功,也可能因 MySQL 配置或缓存导致查询不到。这不是数据没写进去,而是没刷到磁盘或服务没重载元数据。
- 执行完导入后必须重启 MySQL 服务:仅 reload 不够,
systemctl restart mysqld或service mysql restart,否则服务器仍用旧的空时区缓存 - 验证是否真的加载:登录后执行
SELECT COUNT(*) FROM mysql.time_zone_name WHERE Name = 'Asia/Shanghai';,返回 1 才算成功;用LIKE容易误判(比如匹配到Asia/Chongqing) - 注意大小写:MySQL 8.0 默认大小写敏感,
'asia/shanghai'不会命中,必须严格写成'Asia/Shanghai'
配置 default-time-zone = 'Asia/Shanghai' 启动失败
my.cnf 里写了这行,但 MySQL 启动报错退出,日志里出现 Unknown or incorrect time zone: 'Asia/Shanghai'。这不是配置写错了,而是时区表压根没生效。
- 启动失败的直接原因是:MySQL 在初始化阶段就校验该值,此时如果
mysql.time_zone_name表为空或没权限读,就会 fallback 到SYSTEM并报错终止 - 不要跳过验证步骤:必须先确保
SELECT COUNT(*) FROM mysql.time_zone_name WHERE Name = 'Asia/Shanghai';返回非零,再改配置、再重启 - 临时绕过方法(仅调试):把配置改成
default-time-zone = '+08:00',它不依赖时区表,能启动,但无法支持夏令时等动态规则
JDBC 连接时 serverTimezone 参数不生效
服务器时区设成了 Asia/Shanghai,但 Java 应用查出的时间还是 UTC 或错 8 小时。问题不在 MySQL,而在客户端连接参数没对齐。
-
serverTimezone必须显式指定,不能依赖服务器默认值:JDBC URL 中必须带serverTimezone=Asia/Shanghai(URL 编码后为serverTimezone=Asia%2FShanghai) - 避免混用偏移量和命名时区:如
serverTimezone=GMT%2B8虽然能用,但不识别夏令时变化;而serverTimezone=Asia/Shanghai依赖 MySQL 时区表已加载成功 - 驱动类必须更新:老项目若还用
com.mysql.jdbc.Driver,会忽略serverTimezone参数;要换成com.mysql.cj.jdbc.Driver并确保 JDBC jar 是 8.0+ 版本
mysql 库 → 重启 mysqld 刷缓存 → 应用连接时显式声明时区。漏掉任一环,时间都会悄悄错位。











