unix – 在数据库中闰秒处理
如:
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. 那么,如果我在DB中存储Unix纪元(例如ts)(毫秒精度),如何处理以下情况? >如何确保ts总是增加而不是后退? 例如 SELECT * FROM events WHERE ts >= T1 and ts < T1 + 100 上面的SQL将返回发生在T1,T1 1,T1 2,..到T1 99的事件,但由于闰秒,结果可能是错误的,包括闰时间为1秒,如何考虑到这个? 解决方法
我将首先说我在现实生活中没有遇到过这样的问题所以我只会猜测,但这将是一个有根据的猜测.根据
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,闰秒是不可预测的,这使您有两个选择:一个通用的解决方案(假设您有由这些时间戳索引的表)可以始终插入条目,并且在一个条目发生之前最后插入的条目(可能在闰秒内)你可以开始一个’涂抹’过程,这个过程基本上会为条目增加几毫秒,以确保它超出闰秒的范围.当插入的条目将再次具有比先前插入的条目更大的值时,该过程可以停止.我称之为’涂抹’,因为它的某种灵感来自谷歌的“Leap Smear”技术(虽然不完全相同):http://googleblog.blogspot.in/2011/09/time-technology-and-leaping-seconds.html 另一个解决方案可以是(我假设您正在使用Java),您手动检查时间戳是否落在闰秒内.如果是,则阻止对数据库的任何访问并将条目插入队列.当闰秒结束时,只需将FIFO方式的队列插入数据库,以保证您关注的顺序(类似于上面的解决方案,但完全是Java,所以在它甚至触及数据库层之前).你可以通过消除队列并直接插入数据库来优化这一点 – 只需像上面那样“涂抹”一秒钟内的条目. 当然,有一个缺点是你在闰秒中牺牲了一点精度(考虑到闰秒是如此罕见,这不是一个很大的牺牲)但是加分是它很简单并且你的订单得到保证. 如果您或其他任何人发现更好的解决方案,请在这里分享,这个主题非常有趣:) 更新:我已经编写了第三个解决方案的伪代码(完全在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; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |