审计日志的数据库devise

每次我需要devise一个新的数据库时,我都花了相当长的时间思考如何设置数据库模式来保存更改的审计日志。

这里已经提出了一些问题,但我不同意所有情况下都有一个最佳方法:

  • 数据库devise的修订
  • 更新日志审计数据库表的最佳devise
  • 关于捕获审计线索的数据库devise思路

我也偶然发现了这篇关于维护数据库变更日志的有趣文章 ,该文章试图列出每种方法的优缺点。 这本书写得非常好,信息很有趣,但却使我的决定变得更加困难。

我的问题是:有没有可以使用的参考资料,可能是一本书或类似于决策树的东西,我可以根据一些inputvariables来决定应该采用哪种方式,如:

  • 数据库模式的成熟
  • 如何查询日志
  • 有可能需要重新创buildlogging
  • 更重要的是:写或读的performance
  • 正在logging的值的性质(string,数字,斑点)
  • 存储空间可用

我知道的方法是:

1.为创build和修改的date和用户添加列

表格示例:

  • ID
  • _1
  • _2
  • VALUE_3
  • 创builddate
  • modifed_date
  • 由…制作
  • modified_by

主要缺点:我们失去了修改的历史。 提交后无法回滚。

2.只插入表格

表格示例 :

  • ID
  • _1
  • _2
  • VALUE_3
  • 删除(布尔)
  • 用户

主要缺点:如何保持外键最新? 需要巨大的空间

3.为每个表创build一个单独的历史logging表

历史表格示例:

  • ID
  • _1
  • _2
  • VALUE_3
  • VALUE_4
  • 用户
  • 删除(布尔)
  • 时间戳

主要缺点:需要复制所有审计表。 如果模式发生变化,则也需要迁移所有日志。

4.为所有表创build合并历史logging表

历史表格示例:

  • TABLE_NAME
  • 领域
  • 用户
  • NEW_VALUE
  • 删除(布尔)
  • 时间戳

主要缺点:如果需要,我能够重新创buildlogging(回滚)吗? new_value列需要是一个巨大的string,所以它可以支持所有不同的列types。

less数维基平台使用的一种方法是将识别数据和正在审核的内容分开。 它增加了复杂性,但是最终会得到完整logging的审计logging,而不仅仅是编辑的字段清单,然后您必须混合起来,让用户了解旧logging的样子。

例如,如果您有一个名为“ 机会”的表来跟踪销售交易,则实际上可以创build两个单独的表:

机会
Opportunities_Content (或类似的东西)

机会”表将包含用于唯一标识logging的信息,并将包含您为外键关系引用的主键。 Opportunities_Content表格将包含用户可以更改的所有字段,您希望为其保留审计线索。 内容表中的每个logging都将包含自己的PK以及修改date和修改date数据。 机会表将包括对当前版本的引用以及关于何时主logging最初创build以及由谁提供的信息。

这是一个简单的例子:

CREATE TABLE dbo.Page( ID int PRIMARY KEY, Name nvarchar(200) NOT NULL, CreatedByName nvarchar(100) NOT NULL, CurrentRevision int NOT NULL, CreatedDateTime datetime NOT NULL 

内容:

 CREATE TABLE dbo.PageContent( PageID int NOT NULL, Revision int NOT NULL, Title nvarchar(200) NOT NULL, User nvarchar(100) NOT NULL, LastModified datetime NOT NULL, Comment nvarchar(300) NULL, Content nvarchar(max) NOT NULL, Description nvarchar(200) NULL 

我可能会使内容表的PK成为来自PageID和Revision的多列键,如果Revision是一个标识types的话。 您将使用修订列作为FK。 然后,您通过JOINing来取消合并logging,如下所示:

 SELECT * FROM Page JOIN PageContent ON CurrentRevision = Revision AND ID = PageID 

那里可能有一些错误…这是我的头顶。 它应该给你一个替代模式的想法,虽然。

玩笑

如果您正在使用SQL Server 2008,则可能应该考虑更改数据捕获。 这在2008年是新的,可以为您节省大量的工作。

我不知道有什么参考,但是我确定有人写了一些东西。

但是,如果目的仅仅是logging所发生的事情 – 审计日志的最典型的使用 – 那么为什么不简单地保留一切:

 timestamp username ip_address procedureName (if called from a stored procedure) database table field accesstype (insert, delete, modify) oldvalue newvalue 

大概这是由一个触发器维护。

我认为没有什么像一棵决策树。 由于一些利弊(或要求)不是真正可数的。 你如何衡量成熟度?

因此,只需将您的审计日志logging的业务需求排成一行。 尝试预测未来这些要求如何变化,并产生技术要求。 现在你可以比较它的优点和缺点,并select正确/最好的select。

而且放心,不pipe你怎么决定,总会有人认为你做出了错误的决定。 然而,你做了功课,你certificate你的决定是正确的。

我们将为博客应用程序创build一个小型示例数据库。 需要两张桌子:

blog :存储唯一的postID,标题,内容和已删除的标志。 audit :使用loggingID,博客postID,更改types(NEW,EDIT或DELETE)以及更改的date/时间来存储一组基本的历史更改。 以下SQL创buildblog并索引已删除的列:

 CREATE TABLE `blog` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `title` text, `content` text, `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `ix_deleted` (`deleted`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='Blog posts'; 

以下SQL创buildaudit表。 所有列都被编入索引,并为引用blog.id的audit.blog_id定义一个外键。 因此,当我们物理删除一个博客条目时,它的完整审计历史logging也被删除。

 CREATE TABLE `audit` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, `blog_id` mediumint(8) unsigned NOT NULL, `changetype` enum('NEW','EDIT','DELETE') NOT NULL, `changetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `ix_blog_id` (`blog_id`), KEY `ix_changetype` (`changetype`), KEY `ix_changetime` (`changetime`), CONSTRAINT `FK_audit_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `blog` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;