基于时间的统计需求的一点技巧
作者:sky | 分类: 大话技术 | 标签: 大话技术 | 日期:2008-01-27
当遇到一个基于时间的统计需求时,有些情况下是我们可能无法根据系统时间来得到需要统计的时间段(当然是指较精确的两个时间点之间),因为我们的job的执行时间点并不一定非常精确的是真正在我们设定想要的时间点来运行,很可能会有几秒甚至更长的差距。所以我们不可能完全根据job的执行时间点来简单的设定,在OLTP这样的高并发系统上尤其如此。
这种情况下,大多是通过额外方法来记录住上一次统计发生的时间点(在此我们只基于最新数据的统计),然后在下一次统计时就先拿到该时间,从该时间点来开始统计。这里就有一个记录统计时间点的问题:我们到底该记录哪个时间点合适呢?是统计开始的时候还是统计结束的时间点?
我们知道,Oracle为了保证数据的一致性,您在做查询的时候所读取的数据是基于查询开始的那个时刻一致的,也就是说您的查询过程中所读取的数据都是在该时间点的,不管在查询过程中是否有update或者insert都是如此。这就是Oracle非常著名的一致读特性,是基于回滚段和SCN来完成的。而且当查询时间太长以至于在此过程中有太多的transaction进行了commit使该查询需要的回滚段中的数据被覆盖的话,Oracle并不会给您一个不一致的结果,而是返回一个经典的错误,Ora-01555错误(snapshot too old)。
所以,我们最好将统计查询开始的时间定为该次统计的时间点,以此避免在统计过程的新数据在下一次(其实是永远)无法统计进来。但是就算是这样做我们也无法做到绝对精确。因为在更新统计时间和进行统计查询之间不管怎么做都是有一个时间差的,虽然可能只是毫秒级,但还是有可能在这段时间之间有事务提交,而这时候提交的数据同样也是永远无法统计进来了。
此外,还有一个办法可以避免此问题的出现,那就是如果是希望在统计结束的时候再更新您的统计时间的话,您必须将统计时间回退一个时间段,而且这个时间段的长短取决于您的系统中transaction的最长时间,一般一个oltp系统中的事务应该在10分钟之内吧。但是这个解决方案是有一个前提的,那就是我们的统计脚本重复运行(取决于统计脚本)不会影响统计结果。
因此,如何选择更新统计时间点的问题还是需要根据统计需求和系统事务的繁忙程度来决定。



最后一个方案没看明白
grassbell @ January 28, 2008 |
最后的方案就是指统计的时间段与执行时间完全脱离关系,只设定统计时间长短,每次统计的时候,根据上次统计的时候所更新的最后统计时间开始(假定为a时间点),统计固定时间段(假定为x小时)内的数据,再更新最后统计时间为a+x这个时间点,这样就避免了统计本身的事务问题和时间无法保证完全一致的问题。
sky jian @ January 28, 2008 |