type
status
date
slug
summary
tags
category
icon
password

前言

因為計畫將現有環境的 MariaDB 切換為使用 MySQL,測試期間多 ON 了一組 MySQL 結果意外發現兩者的資料集內有一部份有 1 秒的差距,從而發現在當 schema 上只記錄到秒時,MySQL 和 MariaDB 在接收到 INSERT 微秒時有不同的行為模式。

例子

以下事例基於 MySQL 5.7.30 版本與 MariaDB 10.3.10 版本。
首先建立一張表,其中欄位 ts 只到秒,而欄位 ts_3 則是到小數第三位:
在 MySQL 中會將時間欄位四捨五入至形態的位數,因為這樣是符合 SQL 標準的,所以不會出現 error 或者是任何 warring:
在 MariaDB 中則是會將超出形態位數的都無條件捨去(截斷):

解決方案

上述案例可以看到 MySQL 和 Maria 行為的不同,在 MariaDB MDEV-16991 這則中也提出了這個問題,指出 MariaDB 對於時間無條件捨去的部分和其他 database 不同:
Currently MariaDB truncates fractional seconds when changing precision to smaller. This is different from how other databases work.
Currently MariaDB truncates fractional seconds when changing precision to smaller. This is different from how other databases work.
  • TD:target data type
  • SD:source data type
notion image
可以看到這一則的 status 是 CLOSED 在 Fix Version 中標註 10.4.1 版本,讓我們看一下這個版本的 release note 中的 Variables 項目底下可以看到這一項:
New sql-mode setting, TIME_ROUND_FRACTIONAL (MDEV-16991)
New sql-mode setting, TIME_ROUND_FRACTIONAL (MDEV-16991)
也就是說 MariaDB 從 10.4.1 版本開始提供了一新的 sql-mode 當設置後,就會在上述情境下符合 SQL 標準的進行四捨五入:

另外有趣的是 MySQL 在 8.0.1 版本多了一個 sql_mode - TIME_TRUNCATE_FRACTIONAL 這部分看起來是為了 MySQL 5.5 版本中也是無條件捨去(截斷) 行為的提供一個方案供使用者調整兼容性。
Inserting a TIME, DATE, or TIMESTAMP value with a fractional seconds part into a column having the same type but fewer fractional digits resulted in rounding. This differs from MySQL 5.5, which used truncation rather than rounding. To enable control over this behavior, a new TIME_TRUNCATE_FRACTIONAL SQL mode is available. The default is to use rounding. If this mode is enabled, truncation occurs instead. (Bug #16583910, Bug #68760)
Inserting a TIMEDATE, or TIMESTAMP value with a fractional seconds part into a column having the same type but fewer fractional digits resulted in rounding. This differs from MySQL 5.5, which used truncation rather than rounding. To enable control over this behavior, a new TIME_TRUNCATE_FRACTIONAL SQL mode is available. The default is to use rounding. If this mode is enabled, truncation occurs instead. (Bug #16583910, Bug #68760)
可以看到和 MariaDB 正好相反,開啟這個模式就會是直接無條件捨去(截斷)超出型態位數的部分:

參考