代码之家  ›  专栏  ›  技术社区  ›  Vlad

mariadb/mysql NOW()和TIMESTAMPDIFF行为-这是设计的吗?

  •  0
  • Vlad  · 技术社区  · 5 年前

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

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

    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秒>20.2秒 false 一旦四舍五入到1秒精度)。

    我的主要问题是,我的MariaDB设置是否有问题?或者它是一个已知的bug,尤其是MariaDB版本?还是出于设计?

    0 回复  |  直到 5 年前
        1
  •  2
  •   pilcrow    5 年前

    这是故意的。MariaDB/MySQL中的DATETIME算法并没有达到您所期望的效果。

    YYYY-MM-DD HH:MM:SS表示的日期时间值强制为 十进制数 表示为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)
    

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

        2
  •  0
  •   FloridaDBA    5 年前

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

    如果你问的是微秒的话,MariaDB确实有一种处理微秒的方法。

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