我们有几个服务器将行块插入关系数据库中的表中,并且一个服务器偶尔从表中读取新数据.(该表在概念上是某种日志文件 - 数据仅插入但从未修改过,读取服务器显示日志的尾部.)有没有办法让读取服务器只读取新数据?我们可以随意构建表格.
我脑海中浮现但不起作用的一些想法是:
将行标记为已读取不适合我们的应用程序:读取服务器不应更改数据库.(写入数据库以显示内容并不是一件好事,并且可能会有多个会话显示这些内容.)
我们可以在每行填充数据库系统时间的时间戳.问题是这不是提交时间的时间戳,而是插入时间的时间戳.如果您要求数据库"在现在5分钟到现在之间给我所有值",您就不能依赖所有存在的值,因为可能有正在进行的事务.您将不得不再次询问此间隔中的值,这是我想要避免的.
我们可以插入从序列中填充的运行行数.运行事务时出现的问题与使用时间戳时相同.
有没有解决问题的方法,或者我是否必须应用一些启发式方法,例如假设最大事务时间并始终询问"现在 - 最大事务时间"之后写入的值并读取一些数据两次?
如果重要:我们使用Oracle来做到这一点.但我认为只有其他数据库才有效的答案也是普遍感兴趣的.
未指定所使用的数据库,因此尚不清楚该解决方案是否必须整合到现有部署中。有一些可以插入 MySQL 的队列引擎可能会起作用。其中之一是Q4M。一些商业数据库(例如 Oracle)具有时态数据库功能,可以确定事务时间、有效时间和实时时间。
使用 Oracle 时,伪列ora_rowscn或有用的组合scn_to_timestamp(ora_rowscn)都可以有效地提供提交行时的时间戳(发生该行的 SCN)。或者,Oracle Workspace Manager 提供版本启用表,基本上是这样的:您在表上启用版本控制DBMS_WM.EnableVersioning(...),插入带有WMSYS.WM_PERIOD(...)指定有效时间范围的附加字段的行,在读取器上设置工作区的有效范围DBMS_WM.SetValidTime(...)。
您还可以通过将时间戳想法与提交时间启发式相结合,在一定程度上伪造此功能。这个想法只是将“有效时间”与数据一起存储为一列,而不是使用 now() 中的任意增量。换句话说,辅助时间戳列将基于提交时间的启发式 + 一些可接受的延迟窗口(可能是平均提交时间 + 标准差的两倍)来指定某个未来日期(“有效时间”)。或者,使用平均提交时间的某些 ceil() 操作(“至少是提交时间,但四舍五入为 30 秒间隔”)。后者将有效地量化(合并?)读取日志记录的时间。它看起来并没有太大不同,但这种方式可以让您免于读取多余的行。它还解决了读取应用程序在不编写更多代码的情况下无法准确知道写入应用程序的提交时间的问题。