2012-02-06 53 views
4

需要跟踪对数据库中的对象所做的更改。什么是一个很好的解决方案来存储对象的变化历史?

微不足道的实现是获取镜像表,通过触发器将数据插入到数据库中或应用程序内部,但影响性能和随着时间的推移镜像数据库变得巨大并且在原始表必须是改变(镜像表需要反映这种改变)。

因为我最大的要求是对数据库和应用程序性能的影响最小,所以我当前的首选是将更改转储到udp上的syslog-ng中,并将它们存储在纯文本文件中。

毕竟changelog不会被频繁访问,所以甚至可以随着时间的推移将其归档。但显然这样的设置实际访问数据是相当棘手的。

所以我想我的问题是 - 是否有一个系统,至少部分适应我的需求?完美的配合将是UDP访问的无模式附加数据库系统,可自动存档数据(或至少需要最少量的配置)或插入性能降低速度很慢。 MongoDB的? CouchDB的? YourDB?

+0

保存为序列化对象或json的更改(增量更新)数组可能也可以在数组合并以查看当前合并的更改。 – 2012-02-06 17:42:10

+0

是的,这就是我打算做的,问题是要使用什么存储,因此很容易维护它并对其进行时间片分割。 – keymone 2012-02-28 13:20:10

+0

如果问题是存储,您可以将其存储在任何地方,包括文件,数据库中的字段或持久性缓存。这是你的电话。 – 2012-02-29 11:06:41

回答

2

那么,有很多方法可以解决这个问题。我对MongoDB最为熟悉,因此会朝这个方向倾斜。总的来说,我认为它会满足你对性能的需求,并且使用副本集和从奴隶读取的内容可能是需要采取的方法。然而,该版本是不是建立在你可以看到一个办法与Mongoid ::版本这里版本:

Mongoid::Versioning - how to check previous versions?

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

+0

我如何解决归档问题?不会将数据从一个集合移动到另一个集合,以便写入(插入)?另外我正在寻找更多的类似日志的解决方案,并且mongodb似乎提供了太多的功能,我不需要这种情况。 – keymone 2012-02-21 11:12:23

0

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

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

+0

这是个好主意,但不幸的是,sqlite不是无模式的。模型发生变化,我不想花太多时间维护版本/更新日志系统。 – keymone 2012-02-22 16:39:48

1

看一看mongoid history

它跟踪像的历史变迁什么,何时,由何人用版本一起。它也提供了配置选项

1

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中这种方法是debated。有一个关于this topic的问题,并且所提出的解决方案与上面介绍的MongoDB的嵌入式策略类似(因此您应该选择一个您所提供的)。

1

对于简单的目的(MySQL的!),只是做了后,你想保持的记录表UPDATE触发器。

例如,对于表汽车行驶字段

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

创建表 'cars_history'(或等于名)与字段: carId 字段 OLD_VALUE new_value

并添加一个像这样的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 ; 

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

相关问题