【问题标题】:Is there a concurrent-access data storage format that can be version controlled?是否有可以版本控制的并发访问数据存储格式?
【发布时间】:2023-03-03 19:55:01
【问题描述】:

我有一个项目需要对数据存储进行版本控制(例如在 git 或 svn 中)。需要明确的是,我的意思是数据存储的 contents 版本控制,而不是模式。我们将拍摄数据本身的快照,例如能够恢复到以前的状态。还需要分支和合并。

基本要求是:

  • 每个数据存储都可以驻留在自己的目录(存储库)中
  • 可以合并不同版本的数据内容(手动或使用工具)
  • 能够运行基本的选择查询来制作可视化报告

理想情况下:

  • 并发访问安全
  • 一定程度的关系完整性

我查看了各种选项。 SQLite(二进制格式)很难合并。 CouchDB 具有很大的合并可能性(多主复制),但不允许每个数据存储使用不同的目录。纯 JSON 或其他文本文件使查询和关系变得困难。

有没有可以通过这种方式进行版本控制的数据存储格式?你会如何解决这个问题?

编辑(更多上下文):具体用例是实现分布式软件问题跟踪,其风格与Fossil SCM 类似。但是,虽然我对解决此问题的现有工具感兴趣,但我对探索和理解可用于构建此类工具的不同数据存储选项特别感兴趣。

【问题讨论】:

  • 这是一个非常有趣的问题。

标签: database version-control version datastore


【解决方案1】:

我想到的一个解决方案是将您的数据转换为支持版本控制的格式。例如XML。然后,当您想将数据恢复到特定版本时,只需签出相应的 XML 并执行相反的操作。

还有一个基于 XML 的数据库引擎:BaseX

取自BaseX网站:

BaseX 是一个轻量级、高性能和可扩展的 XML 数据库引擎和 XPath/XQuery 3.0 处理器,包括对 W3C 更新和全文扩展的完全支持。交互式和用户友好的 GUI 前端可以让您深入了解 XML 文档。

你也可以看看这个(Oracle):Generating XML Data from the Database

【讨论】:

  • 听起来BaseX和Berkeley DB XML有些相似
  • 事实上Berkeley DB XML 支持 BaseX。记住BaseX 是一个引擎。如果您可以使用Berkeley DB XML,问题就解决了。 :)
【解决方案2】:

注意

所有最新的 SCM 都有原子提交,您不必担心

@RaydelMiranda 的跟进

从另一边你可以有 SQL 后端,但版本和交换只改变 SQL 后端的更新脚本(可以考虑像 Liquibase 这样的全权解决方案 - 我刚刚发现,它可以与 不同 后端:“支持 XML、YAML、JSON 和 SQL 格式”和Rollback 可用于撤消数据库更改)

【讨论】:

    【解决方案3】:

    正如@RaydelMiranda 已经说明的那样,您的基本要求很容易满足。为了完整起见,JSON 也存在(大部分是年轻的)查询语言实现:

    您可以将数据存储在 JSON 中,使用您选择的 DVCS 管理 JSON 文件,并使用上述语言之一来查询数据。您还可以通过仅提供记录 ID 并从其他记录引用这些 ID 来将基本关系信息添加到任何格式。

    据我所知,不存在同时满足任一“理想”要求的工具(@LazyBadger 提到的 Liquibase 看起来很有趣,但它并不对数据库本身进行版本控制)。但是,您自己使用锁来增加对数据文件的并发访问的安全性是相当容易的。请注意,如果您使用库存 (D)VCS,则同时使用 版本控制 已经是安全的。

    关系完整性 是最难解决的问题,尤其是如果您坚持“创建数据库文件并将其粘贴在版本控制系统中”的范例。它几乎肯定会要求你做一些困难和hacky的事情,例如。扩展现有的 XML/JSON 查询系统以保持记录排序并将内存中的查找表保持到原始文件位置(这对于保持可接受的速度是必要的),或修改 SQLite 以使用带有换行符的纯文本文件格式.

    您还可以将范式从内到外:在 SQLite 等 RDBMS 中实现版本控制。这主要是定义“父版本”关系并且从不删除或更新记录,只插入新版本的问题。要在数据库的不同副本之间同步更改,只需交换自上次同步以来所有新插入的记录,父关系将处理其余的(模一些复杂性以防止主键冲突)。这也是像 Git 这样的股票 DVCS 的做法。另外,SQLite 和其他 RDBMS 已经可以安全地同时访问了。

    【讨论】:

    • Liquibase can 版本数据更改 - 这只是 Update 变更集与 Alter 的问题
    • 是的,它可以对数据库进行版本更改,但是如果您想对数据库本身进行版本控制,那就没有用了。
    • “版本数据库”为 1. 版本初始状态 2. 版本变化
    • 这是方法#1,也就是变更集方法。方法 #2 是保留完整快照并在需要时动态计算差异,也就是快照方法。后者在大多数情况下更明智,因为对于前者,比较两个版本,甚至只是在历史中途的某个地方重建一个版本很快就会变得非常昂贵。我认为从最初的问题中也很清楚 MMacdonald 需要一种快照方法。
    【解决方案4】:

    我建议以对 SCM 友好的方式布置数据,即每个数据(问题、客户报告等)一个文件;并在一侧运行一个数据库,其内容可以随时从文件数据中重建。

    CouchDB 等“合并”数据库支持eventual consistency,SCM 也支持;但是,它们之间会略有不同——通常,数据库将用于建立在有点拜占庭式数据结构之上的全自动合并操作(参见例如 Microsoft 论文,Cloud Types for Eventual Consistency),而 SCM 需要(熟练)操作员参加合并并跳过他们为要合并的文本文件中的冲突行分配含义的部分。

    在同构环境(例如从 CouchDB 到 CouchDB)中,最终一致性是一个足够困难的问题,您不想尝试跨系统(从 CouchDB 到 Git,然后返回)。

    假设您既需要数据库(用于临时查询和参照完整性)又需要 SCM;并从您的问题中假设您想要合并的用户体验更接近 SCM;您可能需要进行设置,使 SCM 成为权威数据存储。您可以通过使用 CouchDB 并向 SCM 提交由每个文档一个 JSON 文件组成的转储来快速入门。稍后,如果您发现合并原始 JSON 文件太痛苦,您可以改进转储格式(例如 JSON,但有很多 cmets 来隔离差异块并提供用户帮助)和/或改进工具(例如,在破坏参照完整性的合并操作时警告用户,例如在保留指向不存在的客户报告的错误描述时等)。

    当您制作原型时,请回来为这个问题添加您自己的反馈!

    【讨论】:

    • “当你有原型时,请回来添加你自己的反馈到这个问题!” -- 我同意!
    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 2011-08-24
    • 1970-01-01
    相关资源
    最近更新 更多