变更日志/审核数据库表的最佳设计?[关闭]


114

我需要创建一个数据库表来存储不同的更改日志/审核(添加,删除,修改等内容时)。我不需要存储特别详细的信息,因此我在考虑以下方面:

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

我在这里想念什么吗?显然,我可以继续改进设计,尽管我不打算使其变得复杂(为事件类型或诸如此类的东西创建其他表是不可能的,因为这对我来说很复杂)。


我读了你的答案,我很惊讶没有人谈论法律。我知道一些法律或良好的实践文件解释了我们必须如何实现(只读)审计表。但是我没有比这更多的信息了。我只知道它存在。我21部分11思考审计跟踪中CFR
巴斯蒂安参照Vandamme

Answers:


69

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

event ID
event date/time
event type
user ID
description

想法是相同的:保持简单。

但是,很快就发现这种简约的设计是不够的。典型的审核会引发如下问题:

Who the heck created/updated/deleted a record 
with ID=X in the table Foo and when?

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

object type (or table name)
object ID

到那时,我们的审核日志的设计才真正稳定下来(几年了)。

当然,最后的“改进”仅适用于具有代理键的表。但猜猜怎么了?我们所有值得审核的表都具有这样的键!


我对此设计(基于“描述”的审核跟踪)存在的唯一问题是本地化该领域中使用的语言。
Sam Wilson

@Sam我看不到这样的问题,如果消息是系统生成的,只需在此处使用键作为翻译字符串即可;
JCM 2013年

4
@Hiru:当您将两个或多个不同的概念“混合”到一列中时,迟早会适得其反。例如,如果您“混合”事件类型和对象类型,则会影响查询,例如“显示给定类型的所有对象的记录”和“显示给定类型的所有事件的记录”(查询会更多)复杂,并且很可能会慢得多)。
Yarik

3
除了这些列之外,还可以有一个额外的列用于结构化描述/结构化事件有效负载。此列将以计算机可读格式XML / JSON保存事件详细信息(无论复杂程度如何)。易于序列化,查询(至少在Postgres / MSSQL中),进行推理。
turdus-merula

1
@Benjamin:答案在于领域模型(又名商业模型)。如果模型允许同时创建实体(例如,作为逻辑事务的一部分),那么在具有完全相同时间戳的多个日志记录中,我看不出任何问题。例如,如果创建采购订单(作为交易)可以包括创建N个订单项目,则所有对应的1 + N日志记录将具有相同的时间戳。随后的此类日志分析可以利用此优势,将这些1 + N记录不视为独立记录,而应视为逻辑事务的元素。希望这是有道理的。
Yarik

24

我们还将记录新旧值以及它们来自的列,以及在审计详细信息表中被审计表的主键。想想您需要审计表做什么?您不仅要知道谁进行了更改以及何时进行更改,而且还希望在发生重大更改时知道一种快速的方式将数据放回原处。

在设计时,应编写代码以恢复数据。当您需要恢复时,通常很着急,最好已经做好准备。


1
这真的很好。我不明白为什么人们会忽略最后的帖子。
Maddy.Shik 2010年

3
事件源是在保留历史记录的同时提供回滚功能的另一种方法。
山姆

23

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

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

我们开始构建自己的基于触发器的审核解决方案,我们想审核所有内容,并且手头有一个恢复选项。事实证明这太复杂了,因此我们最终对基于触发器的第三方工具ApexSQL Audit进行了反向工程,以创建我们自己的自定义解决方案。

提示:

  • 包含之前/之后的值

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

  • 如Robert所建议,将数据存储在主数据库之外

  • 将大量时间花在准备报告上-尤其是可能需要恢复的报告

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


2
您为什么要对它进行逆向工程而不是购买?
Jowen 2015年

1
对产品的更多控制权
-Tebe

1
希望他们没有起诉你。
Sorter

9

在这里以及类似的问题中,有很多有趣的答案。我可以从个人经验中添加的唯一内容是:

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

  2. 尽可能合理地标准化。您希望表对原始数据的依赖关系尽可能少。审计表应该简单并且闪电般地从中检索数据。无需在其他表上进行花哨的联接或查找即可获取数据。


8
与具有适当索引的规范化数据相比,非规范化数据的读取速度真的会更快吗?(不是所有的复制都会导致从HDD中读取更多数据吗?)
Sam Sam

4

我们表中的内容:

Primary Key
Event type (e.g. "UPDATED", "APPROVED")
Description ("Frisbar was added to blong")
User Id
User Id of second authoriser
Amount
Date/time
Generic Id
Table Name

通用ID指向表中已更新的行,并且表名是该表的名称(以字符串形式)。不是很好的数据库设计,但是非常有用。我们所有的表都有一个代理键列,因此效果很好。


2
“金额”代表什么?
turdus-merula

这是一个财务应用,所以它是被授权的事情美元价值,等等
WW。

4

通常,自定义审核(创建各种表)是一个不好的选择。可以禁用数据库/表触发器以跳过某些日志活动。自定义审核表可能被篡改。可能会发生异常,导致应用程序崩溃。更不用说设计健壮解决方案的困难。到目前为止,我在此讨论中看到一个非常简单的案例。您需要与当前数据库以及所有特权用户(DBA,Developers)完全隔离。每个主流的RDBMS都提供审计功能,即使DBA也无法禁用这些审计功能,并且会对其保密。因此,RDBMS供应商提供的审核功能必须是首选。其他选择是第三方交易日志读取器或自定义日志读取器,它将分解后的信息推送到消息传递系统中,最终以某种形式的Audit Data Warehouse或实时事件处理程序结束。综上所述:解决方案架构师/“动手实践数据架构师”需要参与根据需求设计这样的系统。通常,这些东西太严重了,以至于不能交给开发人员寻求解决方案。


3

有很多方法可以做到这一点。我最喜欢的方式是:

  1. mod_user在源表中添加一个字段(要记录的字段)。

  2. 创建一个日志表,其中包含要记录的字段以及log_datetimeseq_num字段。 seq_num是主键。

  3. 在源表上构建触发器,只要更改任何受监视的字段,该触发器就会将当前记录插入日志表。

现在,您已获得每项更改及其更改记录。


那么... mod_user字段应该做什么?
康尼

1
告诉你谁做了改变。更新代码应包含一些内容,以将该字段设置为当前用户。
JosephStyons

那么删除呢?如果删除一行,如何处理mod_user列的值?
肯恩·卡尔2014年

@KennCal触发器可以使用虚拟表,您可以在同一触发器内部和之后查看数据。没关系,操作。stackoverflow.com/questions/6282618/...
雷南卡瓦列里

2
@KennCal您是正确的,删除​​触发器将需要为您存储该信息。细节在于细节-如果您使用的是SQL身份验证,则触发器可以仅运行[选择CURRENT_USER]。如果是客户端应用程序,则客户端代码需要宣布其身份。如果是API调用,则删除用户需要是该调用的必需参数。
JosephStyons

1

根据分离原理:

  1. 审计数据表需要与主数据库分开。因为审核数据库可以包含许多历史数据,所以从内存利用率的角度来看,将它们分开是有意义的。

  2. 不要使用触发器来审核整个数据库,因为最终将导致一堆混乱的不同数据库需要支持。您将必须为DB2,SQLServer,Mysql等编写一个。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.