我需要一个数据存储,它不仅要维护对数据所做的更改的历史记录(很容易做到),还要存储对数据的任意数量的提议更改,包括链式提案(即提案提案)。
将这些“更改”视为真正长时间运行的事务,这些事务被保存到数据库中,并且具有几分钟到几年的生命周期。
它们被创建(提议),然后回滚(基本上删除)或提交,当提交时,它们成为对第 3 方可见的有效数据。
当然,这一切都需要某种形式的冲突解决,因为提议的更改可能处于相互矛盾的状态(例如,更改 A 建议删除记录,但更改 B 建议更新它 - 如果首先提交更改 A,那么更改 B 将不得不恢复)
我发现没有现成的产品可以做到这一点。最接近的是 Oracle Workspace Manager,但它不提供 change-on-change 或查看建议删除的功能。我能够做到这一点的唯一方法是在我的版本化表上有一组公共列:
根 ID:必需 - 在创建记录的第一个版本时设置一次与主键相同的值。这代表了所有时间的主键,并被复制到记录的每个版本中。命名关系列时应考虑根 ID(例如 PARENT_ROOT_ID 而不是 PARENT_ID)。由于根 ID 也是初始版本的主键,因此可以根据实际主键创建外键 - 实际所需的行将由下面定义的版本过滤器确定。
更改 ID:必需 - 通过更改创建、更新、删除每条记录
Copied From ID : Nullable - null 表示新创建的记录,not-null 表示该行在更新/删除时是从哪个记录 ID 克隆/分支的
从日期/时间开始生效:可为空 - 空表示建议的记录,非空表示记录何时成为当前记录。不幸的是,不能在 Root ID/Effective From 上放置唯一索引,因为任何 Root ID 都可以有多个空值。(除非您想将自己限制为每条记录的单个建议更改)
生效日期/时间:可为空 - 空表示当前或建议,非空表示何时成为历史。技术上不需要,但有助于加快查找当前数据的查询。此字段可能会被手动编辑损坏,但如果发生这种情况,可以从生效日期/时间重建。
删除标志:布尔值 - 当建议在成为当前记录时删除记录时设置为 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 列(可为空)。因此,第二个查询指的是更改 ID ,而不是单个更改 ID。我在客户端的 change-on-change 场景中过滤多个版本,而不使用 SQL,因此在这些查询中看不到它(客户端在内存中有一个更改 ID 的链接列表,如果检索到超过 1 个版本的行它使用链表来确定使用哪个版本)。
有人知道我可以使用的现成产品吗?我自己处理这个版本控制并引入了各种问题是大量的工作。