As:
The Unix time number is zero at the Unix epoch, and increases by exactly 86400
per day since the epoch. So it cannot represent leap seconds. The OS will slow
down the clock to accomodate for this.
那么,如果我将 Unix 纪元(例如 ts)存储在 DB(毫秒精度)中,如何处理以下情况?
- 如何保证ts始终递增且不倒退?
- 如何从db中精确选择考虑闰秒的100s间隔?
e.g.
SELECT * FROM events WHERE ts >= T1 and ts < T1 + 100
上面的 SQL 将返回 T1、T1+1、T1+2、.. 直到 T1+99 发生的事件,但由于闰秒的原因,如果包含 1s 的闰秒,结果可能会错误,如何取考虑到这一点吗?
首先我要说的是,我在现实生活中没有遇到过这样的问题,所以我只能猜测,但这将是一个有根据的猜测。根据http://en.wikipedia.org/wiki/Unix_time#Encoding_time_as_a_number http://en.wikipedia.org/wiki/Unix_time#Encoding_time_as_a_number当插入闰秒时,问题是 2 次(例如 1998-12-31T23:59:60.00 和 1999-01-01T00:00:00.00)具有相同的 Unix 时间 (915.148.800.000)。删除闰秒后应该不会有任何问题。
根据同一维基百科页面上的注释#2,闰秒是不可预测的,这给您留下了两种选择:一种通用解决方案(假设您有由这些时间戳索引的表)可以始终插入条目,并且一个条目发生在最后插入的条目(可能在闰秒内)您可以开始“涂抹”过程,该过程基本上是向条目添加一些毫秒以确保它超出闰秒的范围。当插入的条目再次具有比先前插入的条目更大的值时,该过程可以停止。我称其为“涂抹”,因为它在某种程度上受到了 Google 的“Leap Smear”技术的启发(尽管不完全相同):http://googleblog.blogspot.in/2011/09/time-technology-and-leaping-seconds.html http://googleblog.blogspot.in/2011/09/time-technology-and-leaping-seconds.html在我看来,这可能会给你的数据库带来一些压力,并且插入查询将是我见过的最复杂的查询之一(如果它甚至可以单独在 SQL 中实现的话)。
另一个解决方案可以是(我假设您使用的是 Java)手动检查时间戳是否落在闰秒内。如果是这样,只需阻止对数据库的任何访问并将条目插入队列中。当闰秒结束时,只需将队列以 FIFO 方式插入数据库即可保证您关心的顺序(类似于上面的解决方案,但完全用 Java 编写,因此在它接触 DB 层之前)。您可以通过消除队列并直接插入数据库来对此进行优化 - 只需像上面一样在一秒钟内“涂抹”条目即可。
当然,缺点是您会牺牲一点闰秒的准确性(考虑到闰秒如此罕见,这并不是一个很大的牺牲),但优点是它很简单并且您的订单得到保证。
如果您或其他人找到更好的解决方案,请在此处分享,这个主题非常有趣:)
更新:我已经为第三个解决方案编写了伪代码(完全在 SQL 查询中)依赖于对闰秒的硬编码检查(比通用解决方案更快)。它可能可以优化很多,但只是为了证明我的观点:
if (newTime is in a leap second){
read smearCount from db;
if (smearCount <= 0) {
smearCount = 1000; // making sure we land outside the leap second
update smearCount in db;
}
newTime += smearCount;
insert newTime into db;
} else { // gradually reducing smearCount by 1 millisecond over the following 1000 insertions
read smearCount from db;
if (smearCount > 0){
smearCount -= 1;
update smearCount in db;
newTime += smearCount;
}
insert newTime into db;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)