21

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

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

任何输入表示赞赏!

UPD

我已将丹尼斯的回答标记为答案,因为他确实回答了 MVCC 是否是我想要的,这就是问题所在。但是,如果有人发现它有用,我已经确定的策略如下详述:

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

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

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

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

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

为了快速启动和运行而不损害我的数据保留,这似乎是一个完美的解决方案。

4

3 回答 3

10

时间旅行

PostgreSQL曾经只有这个功能,并称之为“时间旅行”。请参阅旧文档

spi contrib 模块中有一些类似的功能,您可能想要查看。

复合类型审计触发器

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

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)(使用不同CASE的 for DELETE,其中NEW未定义)。

hstore 审计触发器

但是,如果架构更改以添加新NOT NULL列,那会很痛苦。如果您希望执行类似的操作,请考虑使用 ahstore来归档列,而不是复合类型。我已经在 PostgreSQL wiki 上添加了一个实现

PITR

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

于 2012-09-26T23:27:32.433 回答
5

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

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

有没有更好的办法?

如果我的问题是正确的,那么您正在考虑记录慢慢变化的尺寸

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

时间数据库设计,有一个转折(实时与草稿行)

于 2011-06-16T09:25:58.817 回答
1

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

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

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

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

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

于 2011-06-16T04:02:12.047 回答