【发布时间】:2019-03-07 23:22:42
【问题描述】:
我需要一个数据存储,它不仅可以保存对数据所做更改的历史记录(很容易做到),还可以存储任何数量的对数据提出的更改,包括链式提案(即提案上提案)。
将这些“更改”视为真正长时间运行的事务,这些事务被保存到数据库中,并且具有几分钟到几年的生命周期。
它们被创建(提议),然后回滚(基本上删除)或提交,提交后它们成为对 3 方可见的有效数据。
当然,这一切都需要某种形式的冲突解决,因为提议的更改可能处于相互矛盾的状态(例如,更改 A 提议删除记录但更改 B 提议更新它 - 如果首先提交更改 A,那么更改 B 将有恢复)
我发现没有现成的产品可以做到这一点。最接近的是 Oracle Workspace Manager,但它不提供 change-on-change 或查看建议删除的功能。我能够做到这一点的唯一方法是在我的版本化表上拥有一组公共列:
根 ID:必需 - 在创建记录的第一个版本时设置一次与主键相同的值。这代表了所有时间的主键,并被复制到记录的每个版本中。命名关系列时应考虑根 ID(例如 PARENT_ROOT_ID 而不是 PARENT_ID)。由于 Root ID 也是初始版本的主键,因此可以根据实际主键创建外键 - 实际所需的行将由下面定义的版本过滤器确定。
更改 ID:必需 - 每条记录都是通过更改创建、更新、删除的
Copied From ID:Nullable - null 表示新创建的记录,not-null 表示更新/删除时从哪个记录 ID 克隆/分支该行
从日期/时间开始生效:可空 - 空表示建议的记录,非空表示记录何时成为当前记录。不幸的是,不能在 Root ID/Effective From 上放置唯一索引,因为任何 Root ID 都可以有多个空值。 (除非您想将自己限制为每条记录的单个建议更改)
有效到日期/时间:可空 - null 表示当前或建议,not-null 表示何时成为历史。技术上不需要,但有助于加快查找当前数据的查询。此字段可能会因手动编辑而损坏,但如果发生这种情况,可以从生效日期/时间重建。
删除标志:布尔值 - 当建议在成为当前记录时删除记录时设置为 true。提交删除时,它们的生效日期/时间设置为与生效日期/时间相同的值,将它们从当前数据集中过滤掉。
在某个时间点获取数据当前状态的查询将是;
SELECT * FROM table WHERE EFFECTIVE_FROM <= :Now AND (EFFECTIVE_TO IS NULL OR EFFECTIVE_TO > :Now)
根据变化获取数据当前状态的查询是;
SELECT * FROM table WHERE (CHANGE_ID IN :ChangeIds OR (EFFECTIVE_FROM <= :Now AND (EFFECTIVE_TO IS NULL OR EFFECTIVE_TO > :Now) AND ROOT_ID NOT IN (SELECT ROOT_ID FROM table WHERE CHANGE_ID IN :ChangeIds)))
请注意,此第二个查询包含第一个基于时间的查询,以将当前数据与建议的更改数据重叠。
更改 ID 列是指更改表的主键,该表还包含提供更改时更改功能的父 ID 列(可为空)。因此,第二个查询指的是更改 IDs 而不是单个更改 ID。我在客户端的 change-on-change 场景中过滤多个版本,而不使用 SQL,因此在这些查询中看不到它(客户端在内存中有一个更改 ID 的链接列表,如果检索到超过 1 个版本的行它使用链表来确定使用哪个版本)。
有人知道我可以使用的现成产品吗?自己处理这个版本控制需要大量工作,并且会引入各种问题。
【问题讨论】:
-
你指的是什么数据库? SQL 服务器?甲骨文?
-
任何 RDBMS 都可以用来伪造这个,如上所述(我已经在 Oracle 中完成了)——我正在寻找的是任何可以执行这种数据版本控制的数据存储盒子。
-
如果您的编辑回答了您的问题,您应该回滚该编辑并将其作为答案发布。
标签: database database-versioning temporal-database temporal-tables