像 git 一样存储更改的提交历史记录

spa*_*pas 3 postgresql neo4j

我想为我的数据库实体构建一个类似 git 的版本控制系统。

这些模型是:

Commit
  parent_commit_id

Change
  entity_id
  commit_id
  modifier (added, deleted, modified)

Entity
Run Code Online (Sandbox Code Playgroud)

实体永远不会被真正删除,因此用户可以撤消提交并最终得到有效状态。

听起来很简单,但是:

  • 用户每次点击都会生成一次提交(性能非常重要)
  • 每次提交都会有大约 100 处更改(修改、添加或删除)

因为我们只是存储更改,所以必须计算或存储当前状态。

选项 1:保存每次提交的完整状态意味着我不仅会存储提交中的修改、添加和删除,还会存储每个未更改的实体。我认为这并不是一个真正的选择,因为系统运行时将有超过 2000 万个实体。

选项 2:使用递归公用表表达式计算当前状态。不知道这个速度够不够快

选项 3:在一段时间后执行清理(如 git gc)。这意味着我实际上会删除清理时不再有效的所有实体。这并不是一个真正的选择,因为我希望能够看到所有更改并返回到这些更改。

选项 4:使用图形数据库 (neo4j)?它能以合理的性能处理这样的规格吗?

你还有其他建议吗?

Cra*_*ner 5

您使用 Neo4j 的想法很有趣。快速阅读http://en.wikibooks.org/wiki/Git/Internal_struct已经显示了 git 的复杂程度以及提交拓扑是“有向无环图”这一事实,这有利于Neo4j。

但需要考虑的一件事是您正在规划的模型有多复杂?您想要 git 的部分或全部复杂性吗?如果是这样,像 Neo4j 这样的灵活数据库将是一个好主意。

如果您只想要跟踪单个文件的更改,而不关心多个并发用户,那么请考虑旧的 RCS 系统,该系统存储最新的文件,以及与先前版本的差异链。这可以很容易地存储在两个表中(一个用于文件,一个用于更改)。它与 Dan 的答案相反,它存储第一个文件以及从那里进行的更改。两种方法都有效,但 RCS 方法能够比旧版本更快地检索最新版本,而视频方法检索旧版本的速度最快。由于您从最旧到最新的顺序观看视频,因此他们这样做是有道理的,但我认为对于文件修订,您通常希望首先看到最新的。要更全面地回顾这些方法,请查看 Martin Fowlers 的事件溯源博客。然而,这些方法并没有真正考虑多个并发用户,或者根本没有考虑任何复杂的情况。但它们可以成为更多的基础。

因此,让我们重新考虑更复杂的模型。Neo4j 是无模式的,允许您从简单开始并根据需要增强功能。例如,您可以遵循以下路线:

  • 构建一个简单的类似 RCS 的文件修订系统,在单个图形节点中包含最新内容,以及旧版本的链接链(或旧版本的差异链)
  • 然后你决定需要支持多个文件的提交,你添加树对象(在http://en.wikibooks.org/wiki/Git/Internal_struct中描述),这些可以是图中真实的树结构,带有图链接到文件对象节点的节点。
  • 这些树由提交对象引用,这些对象本身与先前的提交以链的形式链接在一起。一旦有了这些提交链,您可能不再需要文件链,因为您将遍历提交链。每个提交都指向一棵树,树又指向文件。
  • 然后,也许您决定支持分支,因此您添加标签和分支对象,它们链接到提交(以及树和文件)。这自然会导致非循环有向图,显示随时间推移发生的分支和合并。
  • 然后也许您甚至可以考虑添加引用日志,它也可以建模为图表。

当您浏览上面的列表时,总图变得更加丰富和复杂,支持更多的用例。我认为这是构建数据模型的好方法。

通过阅读http://en.wikibooks.org/wiki/Git/Internal_struct可以清楚地看到一件事,即使那里提供了简化的描述,我们也可以看到建模的很多价值(大部分是图形)。链表、树和非循环有向图。在我看来,Neo4j 是一个很好的技术来做到这一点。

那么如何开始呢?例如,看一下一些图表要点示例。在这里似乎相关的一个简单方案是简单版本控制节点方案。然后从那里开始构建。