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.
- TD:target data type
- SD:source data type

可以看到這一則的 status 是
CLOSED
在 Fix Version 中標註 10.4.1
版本,讓我們看一下這個版本的 release note 中的 Variables 項目底下可以看到這一項:也就是說 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)可以看到和 MariaDB 正好相反,開啟這個模式就會是直接無條件捨去(截斷)超出型態位數的部分: