【问题标题】:What would be a good solution to storing change history of objects?什么是存储对象更改历史的好解决方案?
【发布时间】:2012-02-28 04:26:50
【问题描述】:

需要跟踪对数据库中对象所做的更改。

简单的实现是让镜像表通过触发器将记录插入其中,无论是在数据库内部还是在应用程序内部,但这会影响性能,并且随着时间的推移,镜像数据库会变得庞大,并且当必须更改原始表时,基本上会使维护时间加倍(镜像表需要反映这种变化)。

由于我最大的要求是对数据库和应用程序性能的影响最小,我目前的偏好是将更改转储到 syslog-ng 中而不是 udp 并将它们存储在纯文本文件中。

毕竟变更日志不会被频繁访问,因此随着时间的推移将其存档也是可以的。但显然,通过这样的设置,实际访问该数据是相当棘手的。

所以我想我的问题是 - 是否已经有一个系统至少可以部分满足我的需求?完美契合将是 UDP 访问的无模式仅附加数据库系统,可以自动存档数据(或至少需要执行此操作的最少配置量)或插入性能的非常缓慢的下降。 MongoDB?沙发数据库?你的数据库?

【问题讨论】:

  • 保存为序列化对象或 json 的更改数组(增量更新),您也可以在其中进行数组合并以查看当前合并的更改。
  • 是的,这就是我打算做的,问题是要使用什么存储,所以它很容易维护和时间切片。
  • 如果问题是存储,您可以将它存储在任何地方,文件、数据库上的字段或持久缓存。这是你的电话。

标签: mysql mongodb hive nosql


【解决方案1】:

出于简单目的(MySQL!),只需对您要记录的表执行 AFTER UPDATE 触发器即可。

例如对于带字段的桌车

carId(主键) 颜色 制造商 型号

创建一个包含字段的表“cars_history”(或同名): 车牌号 场地 旧值 新值

并像这样添加一个 AFTER UPDATE 触发器:

delimiter //

CREATE TRIGGER trigger_changes
AFTER UPDATE ON cars
FOR EACH ROW
BEGIN
IF OLD.manufacturer <> NEW.manufacturer THEN
  INSERT INTO cars_history
  ( carId, field, old_value, new_value)
  VALUES
  (OLD.carId, 'manufacturer', OLD.manufacturer, NEW.manufacturer);
ELSE IF OLD.color <> NEW.color THEN
  ...
END IF;
END;//
delimiter ;

未经测试,因此可能包含语法错误 :) 希望对您有所帮助!

【讨论】:

    【解决方案2】:

    RavenDB 具有本机功能(但对于生产需求而言,NoSQL 数据库可能还太年轻 - 当然取决于您)

    http://ravendb.net/docs/server/bundles/versioning

    http://www.slideshare.net/jwoglamott/battle-of-nosql-stars-amazons-sdb-vs-mongodb-vs-couchdb-vs-ravendb

    如果你想去MongoDB,这个thread建议了两种实现策略

    Strategy 1: embed history 不会影响您的写入性能和读取,如果您调整代码以避免在不必要时返回历史记录,但是您有一个文档的 16Mb 限制(可能对您来说是障碍)。 Strategy 2: write history to separate collection 需要(显然)两个操作。我同意那里所说的这些(或组合)是 MongoDB 中可用的策略。

    CouchDB 在内部使用 MVCC 方法(您可以按照建议的 here 使用它),但在 SO 中,这种方法是 debatedthis topic 上有一个问题,建议的解决方案类似于上面描述的 MongoDB 嵌入式策略(所以你应该选择你喜欢的那个)。

    【讨论】:

      【解决方案3】:

      看看mongoid history

      它跟踪更改的历史记录,例如更改内容、时间、执行者以及版本。它还提供了配置选项

      【讨论】:

        【解决方案4】:

        我想知道这是否是您正在寻找的解决方案类型: http://www.tonymarston.net/php-mysql/auditlog.html

        这似乎是一个非常简单、优雅的解决方案,数据占用量很小,我希望它对插入时间的影响也很小。

        【讨论】:

          【解决方案5】:

          SQLite 呢?每个数据库都是一个独立的文件,您可以在归档时轻松重命名和移动。如果文件被重命名或自动移动,则在下次插入时创建其他文件。

          关于 SQLite 的唯一问题是并发写入,需要阻止文件写入。它每秒可以执行大约 60 个事务,但您可以在一个事务中执行数千个插入操作(请参阅doc)。

          【讨论】:

          • 这是个好主意,但不幸的是 sqlite 不是无模式的。模型发生变化,我不想花太多时间维护版本控制/变更日志系统。
          【解决方案6】:

          嗯,有很多方法可以解决这个问题。我最熟悉 MongoDB,所以会倾向于那个方向。一般来说,我认为它会满足您对性能的需求,并且使用副本集,从从属设备上读取可能是采用的方法。但是,版本控制不是内置的。您可以在此处查看使用 Mongoid::Versioning 进行版本控制的一种方法:

          Mongoid::Versioning - how to check previous versions?

          你提到的其他解决方案可能有更好的原生支持,但我不能说。希望这至少能给你一些关于 MongoDB 方面的指导。

          【讨论】:

          • 我将如何解决这里的归档问题?不会将数据从一个集合移动到另一个集合以进行写入(插入)吗?我也在寻找更多类似日志的解决方案,而 mongodb 似乎提供了太多我在这种情况下不需要的功能。
          猜你喜欢
          • 2013-03-19
          • 1970-01-01
          • 2022-06-28
          • 2023-03-22
          • 1970-01-01
          • 1970-01-01
          • 2011-11-22
          • 1970-01-01
          • 2016-12-13
          相关资源
          最近更新 更多