【问题标题】:How to keep history of record updates in MySQL?如何在 MySQL 中保留记录更新的历史记录?
【发布时间】:2011-02-01 23:16:25
【问题描述】:

我必须在 PHP 中创建一个代码,让我可以在 MySQL 数据库中保留记录更新的历史记录,以便我可以按日期查找旧版本。

这是我实际想要实现的示例: http://en.wikipedia.org/w/index.php?title=Tunisia&action=history

这些数据主要是我们为生成报告和提取指数而记录的有关公司的数字。

我计划使用 codeigniter,因为它很简单,我正在寻找有关使用相同方法在数据库中保留修改历史的框架或开源项目的想法。

【问题讨论】:

    标签: php mysql logging frameworks


    【解决方案1】:

    这不是记录实际的 SQL 更新。它正在记录数据的更新。它实际上将存储页面的每个修订版,并默认提供最新的修订版。未存储用于它的 SQL 代码。

    因此,您将不得不采取类似的方法。每次数据更改时,您都需要了解数据的更改方式并存储此“补丁”数据。您可能最好存储最新版本,而不必通过所有补丁来获取它。这意味着您将能够看到类似

    ! created file
    * added data to cell D4 'product descript' D5 'set of pens' E5 '£5.99'
    * added data to cell D6 'toaster' E5 '£10'
    & changed data in cell D4 'Product Description'
    

    这些更改中的每一个都需要使用时间戳或何时完成存储。您还需要制定自己的方案来存储对数据的更改。

    另一个更简单的解决方案是使用 wiki 引擎,如果您愿意在网页中工作,它会提供您想要的所有功能。您可能需要花一些时间让它更好地满足您的需求,让人们从更完整的视图而不是原始 wiki 编辑它。

    【讨论】:

      【解决方案2】:

      您必须在应用程序和数据库之间使用额外的层。您可以自己制作一个非常简单的方法(而不是直接调用mysql_query,而是调用您制作的包装它并跟踪更新的函数),或者使用一些现有的 ORM。在伪代码中

      my_mysql_query($query){
          if($query is an update){
              //Log stuff before query
          }
          $r = mysql_query($query);
      
          if ($r && $query is an update){
              //Log stuff after query
          }
          return $r;
      }
      

      然后在您的应用程序中调用my_mysql_query 而不是mysql_query。 您可以检查该表是否是您要跟踪的表,并且可以将该行复制到原始表的副本中。

      如果你使用Doctrine ORM,你可以使用它的Event Listeners来得到你想要的。

      【讨论】:

        【解决方案3】:

        保存版本历史的一个简单方法是创建一个基本相同的表(例如,带有 _version 后缀)。这两个表都有一个版本字段,对于主表,您每次更新都会增加该字段。版本表将在(id, version) 上有一个复合主键。

        每当您对实际表进行更新时,您还会在版本表中插入包含重复数据的新行。每当您想查找版本历史记录时,您所需要做的就是诸如SELECT * FROM content_version WHERE id = CONTENT_ID ORDER BY version 之类的东西。

        如果您使用 Doctrine ORM 之类的东西,它的行为会通过事件侦听器自动为您执行此操作。你可以在这里查看:http://www.doctrine-project.org/documentation/manual/1_2/en/behaviors#core-behaviors:versionable

        【讨论】:

        • 为什么不这样:main table 只包含idversion_id version 表包含所有数据?
        • 谢谢@Shaheer 我要试试这个。
        • @Shaheer 因为大多数查询都是针对当前数据的,因此将历史记录拆分到单独的表中可以确保这些查询不会因为表变为 n 而导致性能损失 倍大。 n 的大小取决于记录的更新频率。
        【解决方案4】:

        如果我理解正确,您只是在特定表格中保存了一个“数字”,并且您想要该数字的修订历史记录?

        我会说:编写您的数据模型,使其包含该数字的历史记录。因此,您不仅可以记录该数字的最新值,还可以保留任何以前的值。

        一个简单的方法是创建一个包含以下字段的表格:

        • 身份证
        • 公司标识
        • 号码
        • 时间戳

        如果你想知道当前号码,就这样做

        SELECT * FROM table WHERE companyId = X ORDER BY timestamp DESC LIMIT 1
        

        如果您想查看所有修订,请执行以下操作:

        SELECT * FROM table WHERE companyId = X
        

        【讨论】:

        • 这是一个仪表板,我正在尝试从一个简单的 Excel 文件迁移。由于我不熟悉 ORM 方式,我更喜欢编写自己的代码。
        • SELECT * FROM table WHERE companyId = X ORDER BY timestamp DESC LIMIT 1
        • 现在这个文本“第一个是当前的。”也已过时,因为结果只有一个(或没有)记录:)
        【解决方案5】:

        最简单的解决方案(取决于您的具体需求)可能是在您的表中添加一个 on update/insert/delete 触发器,这样您就可以在插入/更新/删除数据时执行额外的日志记录。这样即使是对数据库的手动干预也将被覆盖......

        查看http://dev.mysql.com/doc/refman/5.1/en/triggers.html了解更多信息。

        【讨论】:

          【解决方案6】:

          有一个开源(MIT 许可)框架来构建 CRM 和 ERP 类型的数据库驱动的 Web 应用程序。您可以从 http://epe.si/ 下载 EPESI,也可以在 SourceFroge 上下载:http://sourceforge.net/projects/epesi/

          EPESI 的 CRUD 引擎 - 记录浏览器 - 具有非常高效的记录历史以及其他功能,例如高级权限系统(低至字段级别)等等.

          单个记录集将数据存储在多达 10 个表中,并且与数据库无关(使用 PHPAdoDB)。名为 recordset_data 的表存储“原始”数据,更改历史存储在另外 2 个表中:recordset_edit_historyrecordset_edit_history_data

          记录的 edit_history 具有以下结构:

          • ID(此表的主键,索引)
          • 编辑于(时间戳:2008-05-14 15:18:15)
          • 编辑者:(用户 ID)

          记录的edit_history_data结构如下:

          • edit_id = 编辑历史记录中的 ID
          • field = 已更改字段的名称
          • old_value = 已更改字段的值。

          这是一个非常快速和高效的引擎,它不会将更改存储在记录中,而是存储在单个字段级别。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-11-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-01-12
            相关资源
            最近更新 更多