生產環境升級MySQL 5.6.35 版本后,某接口頻繁出現檢查modifyTime不匹配的情況。排查后,發現DB表里的modifyTime 比java程序生成的modifyTime多了1秒。

數據表里的create_time是: 2017-02-17 10:54:48.0 (第一次插入時,modify_time = create_time,但后來資訊被審核,modify_time改變,故以create_time參照)
然而,對比SQL日志里的原始數據,create_time是 2017-02-17 10:54:47.716

-------------------------------------------------------------------
2017-02-17 10:54:47.716 ——> 2017-02-17 10:54:48.0
時間被四舍五入了!根本原因是 Mysql 5.6.4開始,date,datetime,timestamp 支持小數(fractional second part),最大支持6位精度(微秒) 。悲劇的是,如果字段的定義長度 < 小數部分長度,Mysql 5.6會對小數部分進行四舍五入。
從Mysql 5.1遷移到5.6時, 資訊審核表的timestamp長度保持為0 ,而應用傳給Mysql的時間值包含了小數部分,最終被Mysql 四舍五入,變為2017-02-17 10:54:48.0 , 增加了1秒。
Mysql 5.6 官方文檔如下:
MySQL 5.6.4 and up expands fractional seconds support for TIME, DATETIME, and TIMESTAMP values, with up to microseconds (6 digits) PRecision:
Inserting a TIME, DATE, or TIMESTAMP value with a fractional seconds part into a column of the same type but having fewer fractional digits results in rounding, as shown in this example:
....
No warning or error is given when such rounding occurs. This behavior follows the SQL standard, and is not affected by the server's sql_mode setting.
Mysql 5.6 對小數進行 四舍五入操作,不會報錯或Warining,貌似也沒有開關配置是否允許四舍五入。消無聲息就給你做了,你還不能拒絕這個功能,比較坑。
其實除了需要 Mysql 為 5.6.4以上版本,還需要JDBC配合,你才會中招。
mysql-connector-java驅動,由5.1.6升級至5.1.30時,datetime字段的毫秒處理不同。”com.mysql.jdbc.PreparedStatement“中的
(1)5.1.6版本,直接丟棄毫秒部分(代碼飄黃部分)

(2)5.1.30版本,判斷若server端版本為5.6.4及以上時,則將小數部分一同提交至server(代碼飄黃部分)

暫時想到 3種方案:
1、time/datetime/ timestamp 字段增加長度定義, 例如,改成 timestamp(3) 會存儲毫秒,但以后等值查詢的條件,如果不帶毫秒,查不出結果2、在應用程序層面修改,入庫前,攔截datetime、timestamp,去掉小數部分
3、使用5.1.6版本以下的mysql-connector-java驅動(?未驗證)
新聞熱點
疑難解答