向 MySQL 单元格添加时间维度
Posted
技术标签:
【中文标题】向 MySQL 单元格添加时间维度【英文标题】:Adding a time dimension to MySQL cells 【发布时间】:2009-08-10 01:14:35 【问题描述】:有没有办法为 mysql 表中每一行的每一列的每次更改保留时间戳记录?这样我就永远不会丢失任何数据并保留转换的历史记录。行删除可能只是将“已删除”列设置为 true,但可以恢复。
我在看HyperTable,它是 Google 的 BigTable 的开源实现,这个功能让我大吃一惊。如果可以在 MySQL 中使用它会很棒,因为我的应用程序无法处理大量数据来证明部署 HyperTable 是合理的。有关其工作原理的更多详细信息,请参阅here。
是否有任何配置、插件、fork 或任何可以将这一功能添加到 MySQL 的东西?
【问题讨论】:
3 维 SQL 表是一个非常有趣的想法。该语言可以扩展为包含诸如“之前”和“之后”语句之类的语句,它们采用时间戳并返回给定时间之前或之后最接近的编辑。 【参考方案1】:我过去在 php 模型中实现了这一点,类似于 Chaos 所描述的。
如果您使用的是 mysql 5,您还可以使用一个存储过程来完成此操作,该过程与您的表的更新和删除事件挂钩。
http://dev.mysql.com/doc/refman/5.0/en/stored-routines.html
【讨论】:
【参考方案2】:我在自定义框架中执行此操作。每个表定义还生成一个与主表多对一相关的 Log 表,当框架对主表中的行进行任何更新时,它会将行的当前状态插入到 Log 表中。所以我对表的状态有一个完整的审计跟踪。 (我有时间记录,因为我所有的表都有 LoggedAt 列。)
恐怕没有插件,更多的是一种需要融入整个数据库交互方法的做事方法。
【讨论】:
这是一种有趣的方法,但每次更新单个字段时,它都会为一行中的每个字段创建一个副本。我不知道 MySQL 是否足够聪明,可以看到重复并阻止数据库如此快速地增长,但如果不是,那么我需要一种不同的方法。 是的,MySQL 不是那么聪明,所以这并不适合大量更新的表或每行有大量数据的表。【参考方案3】:创建一个存储以下信息的表...
CREATE TABLE MyData (
ID INT IDENTITY,
DataID INT )
CREATE TABLE Data (
ID INT IDENTITY,
MyID INT,
Name VARCHAR(50),
Timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)
现在创建一个存储过程...
INSERT Data (MyID, Name)
VALUES(@MyID,@Name)
UPDATE MyData SET DataID = @@IDENTITY
WHERE ID = @MyID
一般来说,MyData 表只是一个键表。然后将其指向数据表中最新的记录。每当您需要更改数据时,您只需调用将新数据插入数据表的存储过程,然后更新 MyData 以指向最新记录。如果系统中的其他表将自己关闭 MyData.ID 用于外键目的。
这种安排回避了对第二个日志表的需求(并在架构更改时使它们保持同步),但代价是额外的连接和创建新记录时的一些开销。
【讨论】:
我不知道 Views 是如何工作的,但是有没有办法通过让 MyData 看起来像 (ID, Name) 来使其对应用程序透明,其中 Name 将取自最新的 Data MyData 的 DataID 字段指向的记录(应用程序不可见)? 尽管如此,该解决方案仍然会遇到与混乱相同的大小问题,因为每次更新字段时,仍会一遍又一遍地复制未更改的字段。 此解决方案允许您添加多个表以使用视图创建单个复合记录。没有理由简单地拥有 2 张桌子。您可以为经常更改的字段创建一个表,而为很少更改的字段创建另一个表。由于应用程序只能从视图中访问数据,因此您可以在事后重构表而不会影响您的应用程序。本质上,这是在行存储框架内复制列存储数据库节省空间优势的最快方法。【参考方案4】:您是否需要它保持可查询状态,或者这只是为了从错误的编辑中恢复?如果是后者,您可以设置一个 cron 作业来备份 MySQL 存储数据的实际文件并将其发送到版本控制服务器。
【讨论】:
可查询,是的。我想要对连续每个字段的每次编辑的历史记录。设置一个 cron 作业只会不时给我整个数据库的快照,每个数据库之间有很多变化。 我明白了。我不确定是否有任何预先制作的方法来触发文件复制。 (比如 svn 和 post-commit 钩子) 我想我解释得不是很好 - 我设想更新触发文件复制,然后使用 cron 将它们按正常间隔按顺序发送到源代码控制服务器。 嗯,我明白了。但是我猜每次有更新时触发整个数据库的文件副本对于最小的数据集来说会非常昂贵,不是吗? 是的,没错。此外,它不可查询,所以无论如何我的想法都在窗外:)以上是关于向 MySQL 单元格添加时间维度的主要内容,如果未能解决你的问题,请参考以下文章