对数据库持久化对象进行版本控制,我们将如何?
(与版本化数据库模式无关)
与数据库接口的应用程序通常具有由许多表中的数据组成的域对象。假设应用程序在CVS的意义上支持这些域对象的版本控制。
对于某些仲裁域对象,我们将如何设计数据库架构来处理此要求?有经验可以分享吗?
解决方案
我过去用于此目的的一种技术是在数据库中具有"世代"的概念,如果使用颠覆和修订,每次更改都会增加数据库的当前世代数。
每个记录都有与其相关联的2个世代号(表上的2个额外的列),该记录开始对其有效,而该记录对其停止有效。如果数据当前有效,则第二个数字将为NULL或者其他通用标记。
因此要插入数据库:
- 增加世代数
- 插入数据
- 使用有效起始于和有效终止于NULL标记数据的生命周期
如果我们要更新一些数据:
- 将所有将要修改的数据标记为对当前世代号有效
- 增加世代数
- 插入具有当前世代号的新数据
删除只是将数据标记为终止于当前一代。
要获取特定版本的数据,请查找我们所追求的版本,然后查找在这些版本之间有效的数据。
例子:
创建一个人。
|Name|D.O.B |Telephone|From|To | |Fred|1 april|555-29384|1 |NULL|
更新电话号码
|Name|D.O.B |Telephone|From|To | |Fred|1 april|555-29384|1 |1 | |Fred|1 april|555-43534|2 |NULL|
删除fred:
|Name|D.O.B |Telephone|From|To | |Fred|1 april|555-29384|1 |1 | |Fred|1 april|555-43534|2 |2 |
我们将需要一个主表中的主记录,其中包含所有版本之间的通用信息。
然后,每个子表都使用主记录ID +版本号作为主键的一部分。
可以不使用主表来完成此操作,但是根据我的经验,它将使SQL语句更加混乱。
严格版本控制的一种替代方法是将数据分为2个表:当前表和历史表。
当前表具有所有实时数据,并具有内置的所有性能的优点。
任何更改都会首先将当前数据与日期标记一起写到关联的"历史"表中,该日期标记会指出更改的时间。
仔细考虑修订要求。一旦代码库在操作系统中内置了普遍的历史跟踪,它将变得非常复杂。保险承保系统对此尤其不利,其架构经常运行超过1000个表。查询也往往非常复杂,这可能导致性能问题。
如果确实仅需要报告历史状态,请考虑实施"当前状态"事务处理系统,其中的数据仓库结构会悬空以跟踪历史记录。与尝试将临时历史跟踪机制直接嵌入到操作系统中相比,"缓慢更改维度"是一种用于跟踪历史状态的结构要简单得多。
同样,对于"当前状态"系统而言,"更改的数据捕获"更简单,因为对记录的更改已就位,因此记录的主键不会更改,因此我们不必将拥有同一实体的不同版本的记录匹配在一起。有效的CDC机制将使增量仓库装载过程变得相当轻巧,并且可以相当频繁地运行。如果我们不需要最新的历史状态跟踪(几乎,但不是很清楚,以及oxymoron),这可以是一种有效的解决方案,它的代码库比直接内置到应用程序中的完整历史跟踪机制要简单得多。
一种简单的万无一失的方法是在表中添加一个版本列,并存储对象的版本,然后根据该版本号选择适当的应用程序逻辑。
这样,我们还可以以很少的成本获得向后兼容性。哪个总是好
ZoDB + ZEO实现了基于修订的数据库,并且可以完全回滚到任何时间点支持。去检查一下。
不好的部分:Zope被绑住了。
如果我们使用的是Hibernate,则可以选择JBoss Envers。我们只需要用@Audited注释类即可保留其历史记录。