mysql服务器和客户端时区不同,使用jdbc得到的结果差8小时的问题

本文解析了MySQL在不同客户端时区下查询timestamp类型数据时可能出现的时间偏差问题,并提供了通过配置useTimezone参数来解决该问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

默认情况下mysqltime_zoneSYSTEM,也就是mysql的时区和服务器的时区是一样的。一般服务器都是东八区。在使用mysql时,客户端所在的时区一般也是东八区。所以从mysql查询timestamp类型数据时一切正常。

现在如果我们的条件是这样的:

  1. 使用的jdbc url长这样jdbc:mysql://localhost:3306/table_name
  2. 客户端的时区为零时区
  3. mysql的时区是东八区

上面几个条件如果满足了,这时候你从mysql查找timestamp的数据,拿到的timestamp值和数据库中的值是一样的,没有考虑时区的问题,所以事实上是多了8小时。

通过debug,发现jdbcConnectionImpl类中configureTimezone()配置time zone时有几个条件

        String canonicalTimezone = getServerTimezone();

        if ((getUseTimezone() || !getUseLegacyDatetimeCode()) && configuredTimeZoneOnServer != null) {
            // user can override this with driver properties, so don't detect if that's the case
            if (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) {
                try {
                    canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor());
                } catch (IllegalArgumentException iae) {
                    throw SQLError.createSQLException(iae.getMessage(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
                }
            }
        }

        if (canonicalTimezone != null && canonicalTimezone.length() > 0) {
            this.serverTimezoneTZ = TimeZone.getTimeZone(canonicalTimezone);
            ...

getServerTimezone()方法拿到的值默认为nullgetUseTimezone()getUseLegacyDatetimeCode()方法得到的值分别是falsetrue,这样就导致了connector不会使用数据库的time zone。所以我们从数据库内读取timestamp数据,不做任何时区转化。

如果想要开启时区转换,需要将useTimezone设置为true, 即jdbc:mysql://localhost:3306/table_name?useTimezone=true

我们可以看mysql文档对useTimezone描述

useTimezone
Convert time/date types between client and server time zones (true/false, defaults to ‘false’)? This is part of the legacy date-time code, thus the property has an effect only when “useLegacyDatetimeCode=true.”
Default: false

useTimezone设置为true后,还有一点很重要,如果mysqltime_zoneSYSTEM,连接数据库是会报错的,需要给定一个明确的时区。我们可以把数据库的time_zone设置为+08:00,这样timestamp的数据就会根据时区进行转换。 如果不想修改数据库的time_zone,可以在客户端进行设置,指定time_zonejdbc:mysql://localhost:3306/table_name?useTimezone=true&serverTimezone=GMT%2B8,GMT%2B8表示东八区。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值