• 【工作记录】JDBC连接MySQL,跨时区调查CST转Asia/Shangha


    根据业务要求,不同的国家设置jvm参数,来确定当前时区。

    // -Duser.timezone=Asia/Kolkata 印度加尔各答 GMT+05:30
    // -Duser.timezone=Asia/Bangkok 泰国曼谷     GMT+07:00
    // -Duser.timezone=Asia/Shangha 中国上海     GMT+08:00
    

    由于各个国家上线项目不完全相同,部分功能在不同的项目有不同实现方式。数据同步时,发生了跨时区同步数据的情况。
    例如:
    在某个国家部署A服务,在当地时间执行同步任务,可以同步到正确的业务数据,其中业务数据类型使用java.util.Date。
    另一个国家部署B服务,同样业务数据类型使用java.util.Date,在当地时间执行同步任务,不可以同步到正确的业务数据,只好改写为java.lang.String类型。
    调查原因,发现B服务的jdbc的jar包版本太低,不支持自动时区转换,升级版本为6.0.3,可以正确同步数据。

    • JdbcTimestampValueFactory
        public Timestamp createFromTimestamp(int year, int month, int day, int hours, int minutes, int seconds, int nanos) {
            if (year == 0 && month == 0 && day == 0) {
                throw new DataReadException(Messages.getString("ResultSet.InvalidZeroDate"));
            } else {
                synchronized(this.cal) {
                    this.cal.set(year, month - 1, day, hours, minutes, seconds);
                    Timestamp ts = new Timestamp(this.cal.getTimeInMillis());
                    ts.setNanos(nanos);
                    return ts;
                }
            }
        }
    

    但同时发现A服务不需要指定jdbc.url中的serverTimezone=Asia/Shanghai。

    跟踪代码MysqlaSession.configureTimezone(),在不指定serverTimezone时,跟踪获取数据库服务器的时区的代码,获取的确实为CST,但在将转换为对应时区时,A服务将CST转为了Asia/Shanghai,但B服务仍然为CST=Asia/Kolkata。

    • MysqlaSession
        public void configureTimezone() {
            String configuredTimeZoneOnServer = this.getServerVariable("time_zone");
            if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {
                configuredTimeZoneOnServer = this.getServerVariable("system_time_zone");
            }
    
            String canonicalTimezone = (String)this.getPropertySet().getStringReadableProperty("serverTimezone").getValue();
            if (configuredTimeZoneOnServer != null && (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone))) {
                try {
                    canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, this.getExceptionInterceptor());
                } catch (IllegalArgumentException var4) {
                    throw (WrongArgumentException)ExceptionFactory.createException(WrongArgumentException.class, var4.getMessage(), this.getExceptionInterceptor());
                }
            }
    
            if (canonicalTimezone != null && canonicalTimezone.length() > 0) {
                this.serverTimezoneTZ = TimeZone.getTimeZone(canonicalTimezone);
                if (!canonicalTimezone.equalsIgnoreCase("GMT") && this.serverTimezoneTZ.getID().equals("GMT")) {
                    throw (WrongArgumentException)ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("Connection.9", new Object[]{canonicalTimezone}), this.getExceptionInterceptor());
                }
            }
    
            this.defaultTimeZone = this.serverTimezoneTZ;
        }
    

    继续跟进转换代码,在com.mysql.cj.jdbc.util.TimeUtil#loadTimeZoneMappings()中,会加载/com/mysql/cj/jdbc/util/TimeZoneMapping.properties文件,在A服务的资源文件中,有个TimeZoneMapping.properties,并且包含CST=Asia/Shanghai。Git代码提交记录备注为CST TimeZone point to Asia/Shanghai

    • TimeUtil
        private static void loadTimeZoneMappings(ExceptionInterceptor exceptionInterceptor) {
            timeZoneMappings = new Properties();
    
            try {
                timeZoneMappings.load(TimeUtil.class.getResourceAsStream("/com/mysql/cj/jdbc/util/TimeZoneMapping.properties"));
            } catch (IOException var5) {
                throw ExceptionFactory.createException(Messages.getString("TimeUtil.LoadTimeZoneMappingError"), exceptionInterceptor);
            }
    
            String[] var1 = TimeZone.getAvailableIDs();
            int var2 = var1.length;
    
            for(int var3 = 0; var3 < var2; ++var3) {
                String tz = var1[var3];
                if (!timeZoneMappings.containsKey(tz)) {
                    timeZoneMappings.put(tz, tz);
                }
            }
    
        }
    ``
    重要参考链接:
    - https://www.cnblogs.com/sogeisetsu/p/12324161.html
    - https://blog.csdn.net/weixin_37015554/article/details/105198428
    - https://blog.csdn.net/weixin_41917635/article/details/103719481
  • 相关阅读:
    使用CSS3制图
    hdu4585 &amp; BestCoder Round #1 项目管理(vector应用)
    ZooKeeperEclipse 小工具
    svn代码统计工具的金额
    【教你zencart仿站 文章1至6教训 高清1280x900视频下载】[支持手机端]
    [Django]models定义choices 字典中的页面显示值
    xml publisher根据条件显示或隐藏列
    hdu 1398 Square Coins(生成函数,完全背包)
    ubuntu软件中心崩溃
    PHP socket类
  • 原文地址:https://www.cnblogs.com/Candies/p/14121729.html
Copyright © 2020-2023  润新知