更改日志/审计数据库表的最佳设计?

rcp*_*phq 105 database audit database-design

我需要创建一个数据库表来存储不同的更改日志/审核(当添加,删除,修改等内容时).我不需要存储特别详细的信息,所以我想的是:

  • id(用于活动)
  • 触发它的用户
  • 事件名称
  • 事件描述
  • 事件的时间戳

我在这里错过了什么吗?显然我可以继续改进设计,虽然我不打算让它变得复杂(为事件类型创建其他表格或类似的东西是不可能的,因为它是我需要的复杂因素).

Yar*_*rik 63

在我正在研究的项目中,审计日志也是从非常简约的设计开始的,就像你描述的那样:

event ID
event date/time
event type
user ID
description
Run Code Online (Sandbox Code Playgroud)

这个想法是一样的:保持简单.

然而,很明显这种简约设计还不够.典型的审计正在沸腾到这样的问题:

Who the heck created/updated/deleted a record 
with ID=X in the table Foo and when?
Run Code Online (Sandbox Code Playgroud)

因此,为了能够快速回答这些问题(使用SQL),我们最终在审计表中增加了两个列

object type (or table name)
object ID
Run Code Online (Sandbox Code Playgroud)

那时我们的审计日志设计确实稳定了(现在几年).

当然,最后的"改进"仅适用于具有代理键的表.但猜猜怎么了?我们所有值得审核的表都有这么一把钥匙!

  • @Hiru:当你将两个或多个不同的概念"混合"到一个列中时,它往往会迟早会适得其反.例如,如果您"混合"事件类型和对象类型,它将影响查询,例如"为给定类型的所有对象显示记录"和"向我显示给定类型的所有事件的记录"(查询将更多复杂,最有可能工作得慢得多. (3认同)
  • 除了这些列之外,还可以有一个额外的列用于“结构化描述/结构化事件有效载荷”。此列将以计算机可读格式XML / JSON保存事件详细信息(无论复杂程度如何)。易于序列化,查询(至少在Postgres / MSSQL中),进行推理。 (3认同)
  • 我在这个设计中遇到的唯一问题(基于“描述”的审计跟踪)是对该领域使用的语言进行本地化。 (2认同)

小智 23

您可能还需要审核其他一些内容,例如表/列名称,进行更新的计算机/应用程序等等.

现在,这取决于您真正需要的详细审核以及在什么级别.

我们开始构建自己的基于触发器的审计解决方案,我们希望审计所有内容,并且还有一个恢复选项.事实证明这太复杂了,所以我们最终以逆向工程触发器为基础的第三方工具ApexSQL Audit来创建我们自己的自定义解决方案.

提示:

- 包括值之前/之后

- 包括3,4列用于存储主键(如果它是复合键)

- 如Robert已经建议的那样存储主数据库外的数据

- 在准备报告时花费相当多的时间 - 特别是那些你可能需要恢复的报告

-Plan用于存储主机/应用程序名称 - 这可能对跟踪可疑活动非常有用

  • 为什么要对它进行逆向工程而不是购买? (2认同)
  • 更好地控制产品 (2认同)

HLG*_*GEM 21

我们还记录旧值和新值以及它们来自的列以及要在审计详细信息表中审计的表的主键.想一想你需要的审计表是什么?您不仅想知道谁进行了更改以及何时进行更改,而且当发生不良更改时,您需要快速将数据放回原处.

在设计时,您应该编写代码来恢复数据.当你需要恢复时,通常是匆忙,最好已经做好准备.

  • [事件采购](http://martinfowler.com/eaaDev/EventSourcing.html)是一种在保持历史记录的同时提供回滚功能的替代方法. (3认同)

Rob*_*eal 8

这里和类似的问题有很多有趣的答案.我个人经验中唯一可以补充的是......

  1. 将审计表放在另一个数据库中.理想情况下,您希望与原始数据分离.如果需要还原数据库,则不需要还原审计跟踪.

  2. 尽可能合理地反规范化.您希望表具有尽可能少的原始数据依赖性.审计表应该简单快捷,以便从中检索数据.没有花哨的联接或查找其他表来获取数据.

  • 与具有适当索引的标准化数据相比,非标准化数据的读取速度是否真的更快?(并不是所有的复制都会导致从HDD中读取更多数据吗?) (5认同)

小智 5

根据分离原理:

  1. 审计数据表需要与主数据库分开。由于审计数据库可能包含大量历史数据,因此从内存利用率的角度来看,将它们分开是有意义的。

  2. 不要使用触发器来审计整个数据库,因为您最终会得到一堆不同的数据库需要支持。您必须为 DB2、SQLServer、Mysql 等编写一个。


小智 5

一般来说,自定义审计(创建各种表)是一个糟糕的选择。可以禁用数据库/表触发器以跳过某些日志活动。自定义审计表可以被篡改。可能会发生异常,从而导致应用程序失败。更不用说设计一个强大的解决方案的困难了。到目前为止,我在本次讨论中看到了一个非常简单的案例。您需要与当前数据库和任何特权用户(DBA、开发人员)完全分离。每个主流 RDBMS 都提供审计工具,即使是 DBA 也无法禁用、秘密篡改。因此,RDBMS 供应商提供的审计功能必须是第一选择。其他选项是 3rd 方事务日志阅读器或自定义日志阅读器,它将分解的信息推送到消息传递系统中,最终以某种形式的审计数据仓库或实时事件处理程序结束。总之:解决方案架构师/“动手数据架构师”需要根据需求参与确定这样的系统。将问题交给开发人员寻求解决方案通常太严肃了。