【问题标题】:Database Content Versioning数据库内容版本控制
【发布时间】:2018-05-13 02:11:43
【问题描述】:

我有兴趣保留数据库中某些表上发生的每次更改的运行历史记录,从而能够重建数据库的历史状态以进行分析。

我正在使用 Postgres,而这个 MVCC 东西似乎我应该能够为此目的利用它,但我找不到任何文档来支持这一点。我可以做吗?有没有更好的办法?

感谢任何输入!

UPD

我已将 Denis 的回答标记为答案,因为他确实回答了 MVCC 是否是我想要的,这就是问题所在。但是,我已经确定的策略在下面详细说明,以防有人发现它有用:

Postgres 功能可以满足我的需求:在线备份/时间点恢复。

http://www.postgresql.org/docs/8.1/static/backup-online.html 解释了如何使用此功能,但本质上您可以将此“预写日志”设置为存档模式,拍摄数据库快照(例如,在它上线之前),然后持续存档 WAL。然后,您可以随时使用日志重放来调用数据库的状态,如果您选择(通过不断地在备用服务器上重放新的 WAL),还可以使用热备用。

也许这种方法不像其他保存历史的方法那样优雅,因为您需要为要查询的每个时间点实际构建数据库,但是它看起来非常容易设置并且丢失零信息。这意味着当我有时间改进对历史数据的处理时,我将拥有一切,因此能够将笨重的系统转变为更优雅的系统。

使它如此完美的一个关键事实是,我的“有效时间”与特定应用程序的“交易时间”相同 - 如果不是这种情况,我只会捕获“交易时间”。

在我发现 WAL 之前,我正在考虑只拍摄每日快照之类的东西,但所涉及的大尺寸要求和数据丢失并不适合我。

为了快速启动和运行而不影响我从一开始的数据保留,这似乎是完美的解决方案。

【问题讨论】:

  • 您绝对应该看看 NeXtep Designer IDE - 您可以将您的数据库置于版本控制之下并从头开始重新创建任何版本或迁移任何增量、同步数据库状态等。
  • @ChristopheFondacci 您还在使用您的 NexStep Designer IDE 吗?
  • @CMCDragonkai 我们目前正在提供维护和错误修复。我们当时无法开发新功能,但我们仍在执行任务中几乎每天都在使用该产品。

标签: postgresql versioning mvcc


【解决方案1】:

时间旅行

PostgreSQL习惯只有这个功能,称之为“时间旅行”。见the old documentation

spi contrib module 中有一些类似的功能,您可能想看看。

复合类型审计触发器

我通常做的是使用触发器将更改与时间戳一起记录到存档表,并针对这些进行查询。如果表结构不会改变,你可以使用类似的东西:

CREATE TABLE sometable_history(
    command_tag text not null check (command_tag IN ('INSERT','DELETE','UPDATE','TRUNCATE')),
    new_content sometable,
    change_time timestamp with time zone
);

您的版本控制触发器可以只是 insert into sometable_history(TG_OP,NEW,current_timestamp)(对于 DELETE 使用不同的 CASE,其中未定义 NEW)。

hstore 审计触发器

如果架构更改为添加新的NOT NULL 列,那会很痛苦。如果您希望执行类似的操作,请考虑使用 hstore 来归档列,而不是复合类型。我已经加了an implementation of that on the PostgreSQL wiki already

PITR

如果您想避免对主数据库的影响(增长的表等),您可以交替使用continuous archiving and point-in-time recovery 来记录 WAL 文件,这些文件可以使用recovery.conf 随时重播到任何时刻。请注意,WAL 文件很大,它们不仅包括您更改的元组,还包括 VACUUM 活动和其他详细信息。您需要通过clearxlogtail 运行它们,因为如果它们是归档超时的部分段,它们最后可能会有垃圾数据,那么您需要对它们进行大量压缩以进行长期存储。

【讨论】:

    【解决方案2】:

    我正在使用 Postgres,而这个 MVCC 东西似乎我应该能够为此目的利用它,但我找不到任何文档来支持这一点。可以吗?

    不是真的。有一些工具可以查看死行,因为自动清理最终会被回收。

    有没有更好的办法?

    如果我的问题正确,您正在考虑登录 slowly changing dimensions

    您可能会发现这个最近的相关主题很有趣:

    Temporal database design, with a twist (live vs draft rows)

    【讨论】:

    • 感谢您的意见,我希望答案可能是肯定的,但很高兴知道我不能走哪条路。我过去使用过有效时间数据库设计,并将研究 SCD 作为替代方案。
    【解决方案3】:

    我不知道有任何为此目的而构建的工具/产品。

    虽然这可能不是您所要求的,但您可以配置 Postgresql 以记录 ddl 更改。设置 log_line_prefix 参数(尝试包括 %d、%m 和 %u)并将 log_statement 参数设置为 ddl 应该可以让您合理地了解谁做了什么 ddl 更改以及何时更改。

    话虽如此,我不相信记录 ddl 是万无一失的。例如,考虑以下情况:

    1. 多个模式有一个同名的表,
    2. 其中一个表已更改,并且
    3. ddl 没有完全限定表名(依靠搜索路径来获得正确),
    4. 那么可能无法从日志中得知实际更改了哪个表。

    另一种选择可能是像上面那样记录 ddl,然后让观察程序在每次记录 ddl 条目时执行数据库模式的 pg_dump。您甚至可以将新转储与之前的转储进行比较,并仅提取已更改的对象。

    【讨论】:

      最近更新 更多