mysql精度丢失无法入库_Mysql时间精度丢失问题

在MySQL数据库中,使用DateTime(3)类型字段时遇到精度丢失问题,只保留到秒,不包含毫秒。经过排查,发现原因是mysql-connector-java版本低于5.1.23,存在一个Bug导致时间精度丢失。升级到5.1.23以上版本或设置useServerPrepStmts=true可以解决,但后者在Mysql5.7.22以下版本有bug。解决方案是更新连接器到修复Bug的版本。
摘要由CSDN通过智能技术生成

为什么80%的码农都做不了架构师?>>>

6936d1565ae689371725cdb5fc51c415.png

这两天发现一个问题,在数据库中使用了DateTime(3)类型的字段,但是发现本地的ide中入库的数据,所有的毫秒数为000,只能精确到秒,但是dev环境的服务器却是可以精确到正常的毫秒数。由于代码包和数据库都是相同的,问题难以排查,所以直接进行了跟踪源码进行排查。发现最后的原因,是本地的mysql-connector-java版本是5.1.15而服务器上面是5.1.45,版本不同导致的问题。mysql-connector-java这个jar包在5.1.22及以下的版本中存在一个Bug,会将时间精度丢失,5.1.23及以上版本修复了这个bug。

下面看下源码中产生Bug的地方,PrepareStamtement.setTimestampInternal

private void setTimestampInternal(int parameterIndex, Timestamp x, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws SQLException {

if (x == null) {

this.setNull(parameterIndex, 93);

} else {

this.checkClosed();

if (!this.useLegacyDatetimeCode) {

this.newSetTimestampInternal(parameterIndex, x, targetCalendar);

} else {

String timestampString = null;

Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? this.connection.getUtcCalendar() : this.getCalendarInstanceForSessionOrNew();

synchronized(sessionCalendar) {

x = TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar, x, tz, this.connection.getServerTimezoneTZ(), rollForward);

}

if (this.connection.getUseSSPSCompatibleTimezoneShift()) {

this.doSSPSCompatibleTimezoneShift(parameterIndex, x, sessionCalendar);

} else {

synchronized(this) {

if (this.tsdf == null) {

this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss''", Locale.US);

}

//这里将精度丢失了,mysql-connector-java <=5.1.22 都会有这个问题,当然如果采用ServerPrepareStatement不存在这个时间转换,也就不会存在这个问题了,如果采用5.1.22以上的版本,这个bug修复之后同样也不会存在这个问题

timestampString = this.tsdf.format(x);

this.setInternal(parameterIndex, timestampString);

}

}

}

this.parameterTypes[parameterIndex - 1 + this.getParameterIndexOffset()] = 93;

}

}

这里还提供一种方式,采用设置useServerPrepStmts=true也可以解决这个问题,但是useServerPrepStmts=true获取的是ServerPrepareStatement,不是PrepareStatement,并且useServerPrepStmts=true这个参数在Mysql5.7.22以下的版本中存在一个bug,即union all 中包含Date类型的字段的时候会抛异常,官方bug:https://bugs.mysql.com/bug.php?id=87534 ,所以建议一般设置成false(默认值也是false)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值