【问题标题】:mariadb/mysql NOW() and TIMESTAMPDIFF behavior - is it by design?mariadb/mysql NOW() 和 TIMESTAMPDIFF 行为 - 是设计使然吗?
【发布时间】:2020-02-03 14:21:07
【问题描述】:

只是将一些代码从 OracleDB 移植到 MariaDB,并将一些 OracleDB 表达式(如 SYSDATE - ? / 1440)转换为 MariaDB 表示法(这似乎很合适:NOW() - interval 60 * ? second)。

在调试以下行为不端的表达式时偶然发现了我怀疑是已知错误或记录在案的行为(请帮助)(主要是比较 2 个历史“锁定”的持续时间)

WHERE (a.expirationDt - a.acquisitionDt) > (b.expirationDt - b.acquisitionDt)

在 OracleDB 中 - 此表达式始终/可靠地工作。 在 MariaDB 中 - 它似乎取决于减去的时间戳是否属于同一分钟(然后减法导致正确的秒数)或者它们是否来自两个不同的分钟(然后减法结果似乎被填充/四舍五入到最接近的分钟),从而产生违反直觉的结果。

这是一个小演示(基本上使用now() 和“20 秒前”):

root@localhost> maria "select now(), now() - interval 60 * 1/3 second,  now() - interval 60000000 * 1/3 microsecond, now() - (now() - interval 60 * 1/3 second), now() - (now() - interval 60000000 * 1/3 microsecond), TIMESTAMPDIFF( second,  now() - interval 60 * 1/3 second, now()) from dual"
2020-02-03 13:51:59.0
2020-02-03 13:51:39.0
2020-02-03 13:51:39.0
20.0000
20.000000
20
root@localhost> maria "select now(), now() - interval 60 * 1/3 second,  now() - interval 60000000 * 1/3 microsecond, now() - (now() - interval 60 * 1/3 second), now() - (now() - interval 60000000 * 1/3 microsecond), TIMESTAMPDIFF( second,  now() - interval 60 * 1/3 second, now()) from dual"
2020-02-03 13:52:02.0
2020-02-03 13:51:42.0
2020-02-03 13:51:42.0
60.0000
60.000000
20

我知道TIMESTAMPDIFF 看起来不错,并且可以相应地重写 SQL(只需要确保如何以亚秒级精度正确工作,假设“20.4 sec > 20.2 sec”将返回 false 一旦四舍五入为 1 -sec 精度)。

我的主要问题 - 我的 MariaDB 设置有问题吗?或者它是特定 MariaDB 版本中的已知错误?还是设计使然?

【问题讨论】:

    标签: mysql timestamp mariadb sysdate timestampdiff


    【解决方案1】:

    这是设计使然。 MariaDB/MySQL 中的 DATETIME 算法并没有达到您的预期。

    表示 YYYY-MM-DD HH:MM:SS 的 DATETIME 值被强制转换为表示为 YYYYMMDDHHMMSS 的十进制数字(并用零值填充缺失的秒数,例如)。

    一个来自 MySQL 的例子:

    mysql> SELECT CAST('2020-02-02 00:01' AS DATETIME) - CAST('2020-02-02 00:00:01' AS DATETIME),
        -> 20200202000100 - 20200202000001 \G
    *************************** 1. row ***************************
    CAST('2020-02-02 00:01' AS DATETIME) - CAST('2020-02-02 00:00:01' AS DATETIME): 99
                                                   20200202000100 - 20200202000001: 99
    1 row in set (0.00 sec)
    

    正如您所发现的,对于这种算术,您必须使用特定于日期/时间操作的函数。

    【讨论】:

    • 哦,所以再过一分钟,结果就是加了 40(60 对 100,十进制错误),明白了,谢谢你的详细回答!
    【解决方案2】:

    您是否连续两次运行相同的查询,并针对时间戳差异返回不同的结果?

    MariaDB 确实有一种处理微秒的方法,如果这是您所要求的。

    https://mariadb.com/kb/en/microseconds-in-mariadb/

    【讨论】:

    • 是的,只是运行相同的 now() - (now() - interval 60 * 1/3 second) - 它返回 20 秒(正确)或 60(不正确),具体取决于 now()(now() - interval 60 * 1/3 second) 是在同一分钟内,还是在不同 (相邻)分钟:(
    猜你喜欢
    • 2017-12-09
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 2022-01-13
    • 2020-08-08
    • 2014-06-08
    • 1970-01-01
    相关资源
    最近更新 更多