我在调试失败的集成测试时遇到了一个奇怪的问题。我似乎得到了不一致的结果,具体取决于以下查询的排序方向(ASC
/ DESC
):
SELECT u.id, u.last_updated FROM user u WHERE u.id IN (36, 37, 38, 39, 40) ORDER BY u.last_updated ASC;
以上查询返回这些结果,正如我所料:
id last_updated
=======================
36 2015-07-15 19:45:34
37 2015-07-15 19:45:34
38 2015-07-15 19:45:34
39 2015-07-15 19:45:35
40 2015-07-15 19:45:35
但是,如果我将排序顺序从ASC
切换到DESC
,我就明白了:
id last_updated
=======================
39 2015-07-15 19:45:35
40 2015-07-15 19:45:35
36 2015-07-15 19:45:34
37 2015-07-15 19:45:34
38 2015-07-15 19:45:34
当查询按降序排列时,就好像MySQL无法区分日期之间的差异超过第二精度。
如果我更改日期以便每个last_updated
值之间有1秒的间隔,那么排序在两个方向上都能正常工作。
这些查询是通过基于Grails / Hibernate的应用程序执行的。如果我在我的应用程序中添加一些调试代码,我可以看到日期都是不同的,精确到1毫秒:
1436989535410, 1436989535646, 1436989534516, 1436989534990, 1436989534751
所以数据存储到足够的精度......
用户表声明如下所示:
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`last_updated` datetime NOT NULL,
...
)
我正在使用MySQL 5.6.15。
使用H2 Java内存数据库进行测试时,相同的查询/集成测试正常工作。
修改
有趣的是,它确实看起来有些精确度正在丢失。如果我运行以下查询:
SELECT u.id, u.last_updated, UNIX_TIMESTAMP(u.last_updated) FROM user u WHERE u.id IN (36, 37, 38, 39, 40) ORDER BY u.last_updated ASC;
我明白了:
id last_updated unix timestamp
=======================================
36 2015-07-15 19:45:34 1436985934
37 2015-07-15 19:45:34 1436985934
38 2015-07-15 19:45:34 1436985934
39 2015-07-15 19:45:35 1436985935
40 2015-07-15 19:45:35 1436985935
我想Hibernate正在缓存更精确的预持久性日期值,并在我尝试在我的应用程序中调试时将它们还给我...
答案 0 :(得分:2)
尝试将last_updated
字段更改为DATETIME(6)
而不是DATETIME
。这样您就可以获得微秒级的分辨率。 MySQL Reference.
答案 1 :(得分:0)
您可以将id
字段添加为相等秒的分母,因为插入是atomar(先到先发服务)
... 40) ORDER BY u.last_updated ASC, id ASC;
RESP。
... 40) ORDER BY u.last_updated DESC, id DESC;