【发布时间】:2009-08-13 21:59:36
【问题描述】:
我想为我的小型 CodeIgniter 应用程序创建一个简单的审计系统。这样它会在条目被编辑之前拍摄表格条目的快照。我能想到的一种方法是创建一个news_audit 表,它将复制新闻表中的所有列。它还将为每个更改创建一个新记录,并添加添加的日期列。您对将此类功能构建到 PHP Web 应用程序中有何看法和意见?
【问题讨论】:
标签: php mysql codeigniter
我想为我的小型 CodeIgniter 应用程序创建一个简单的审计系统。这样它会在条目被编辑之前拍摄表格条目的快照。我能想到的一种方法是创建一个news_audit 表,它将复制新闻表中的所有列。它还将为每个更改创建一个新记录,并添加添加的日期列。您对将此类功能构建到 PHP Web 应用程序中有何看法和意见?
【问题讨论】:
标签: php mysql codeigniter
在决定使用哪种解决方案之前,需要考虑以下几点:
如果您的表很大(或可能变大),您的审计跟踪需要按照您的描述放在单独的表中,否则性能会受到影响。
如果您需要一个不能(可能)修改的审计,除了添加新条目,它只需要对应用程序具有 INSERT 权限(并且要成为铸铁需要在专用的日志服务器上......)
我会避免在同一个表中创建审计记录,因为这可能会使其他开发人员感到困惑(他们可能没有意识到他们需要过滤掉没有日期的旧记录)并且会使表中出现审计行混乱,这将迫使db 缓存比它需要的更多的磁盘块(== 性能成本)。如果您的数据库不索引 NULLS,那么正确索引这可能是一个问题。如果您选择为所有版本添加时间戳,则查询最新版本将涉及子查询。
如果您的数据库支持,解决此问题的最简单方法是在您的新闻表上创建一个 UPDATE TRIGGER,将旧值复制到一个单独的审计表中,该表只需要 INSERT 权限)。通过这种方式,逻辑被内置到数据库中,因此您的应用程序不需要关心它,它们只是更新数据,数据库负责保存更改日志。触发器的主体将只是一个 INSERT 语句,因此如果您之前没有编写过它应该不会花费很长时间。
如果我知道您使用的是哪个数据库,我可能会发布一个示例...
【讨论】:
我们所做的(您可能希望根据大小和使用情况预先设置归档),但我们创建了一个审计表,用于存储用户信息、时间以及 XML 中的更改以及表名。
如果您使用的是 SQL2005+,则可以轻松搜索 XML 以查找需要的更改。
然后我们向表中添加触发器以捕获我们想要审核的内容(插入、删除、更新...)
然后通过简单的序列化,我们能够恢复和复制更改。
【讨论】:
我们在这里看到的是什么规模?平均而言,条目会经常编辑还是不经常编辑?
根据您对平均项目的预期编辑次数,存储大数据块的差异可能比存储数据的完整副本更有意义。
【讨论】:
我喜欢的一种方法是将其放入表格本身。您只需添加一个“valid_until”列。当您“编辑”一行时,您只需复制它并在旧行上标记“valid_until”字段。有效行是没有设置“valid_until”的行。简而言之,您将其设为写时复制。不要忘记将主键设置为原始主键和 valid_until 字段的组合。还要设置约束或触发器,以确保每个 ID 只能有一行没有设置它的 valid_until。
这有好处也有坏处。好处是桌子少了。缺点是表格中的行数更多。如果您经常需要访问旧数据,我会推荐这种结构。只需在查询中添加一个简单的 WHERE,您就可以查询表在前一个日期/时间的状态。
如果您只是偶尔需要访问旧数据,那么我不推荐这样做。
您可以通过构建Temportal database 将其发挥到极致。
【讨论】:
在中小型项目中,我使用以下规则集:
patches/)086_added_login_unique_constraint.sql)这样可以保证,您可以轻松地重新创建数据库架构,而无需导入整个数据转储。创建这样的补丁是轻而易举的事。只需在控制台/UI/web 前端运行命令,如果成功,将其复制粘贴到补丁中。然后只需将其添加到 repo 并提交更改。
这种方法可以很好地扩展。为 PHP/PostgreSQL 项目工作,该项目由 1300 多个类和 200 多个表/视图组成。
【讨论】: