在SQL Server中创建审计触发器

Mik*_*ole 30 sql-server audit triggers sql-server-2005

我需要在SQL Server 2005数据库中的两个表上实现更改跟踪.我需要审核添加,删除,更新(详细了解更新内容).我正计划使用触发器来执行此操作,但在Google上进行搜索后,我发现错误地执行此操作非常容易,而且我想在开始时避免使用它.

任何人都可以发布更新触发器的示例,以优雅的方式成功完成此操作吗?我希望最终得到一个具有以下结构的审计表:

  • ID
  • LOGDATE
  • 表名
  • TransactionType(更新/插入/删除)
  • 的recordId
  • 字段名
  • 的OldValue
  • 的NewValue

......但我愿意接受建议.

谢谢!

Rem*_*anu 35

我只想提出几点意见:

使用代码生成器您不能只有一个程序来跟踪所有表,您需要在每个跟踪表上生成类似但不同的触发器.这种工作最适合自动代码生成.在您的位置,我将使用XSLT转换从XML生成代码,并且可以从元数据自动生成XML.这使您可以在每次更改审计逻辑/结构或添加/更改目标表时通过重新生成触发器来轻松维护触发器.

考虑审计的容量规划.到目前为止,跟踪所有值更改的审计表将是数据库中最大的表:它将包含所有当前数据和当前数据的所有历史记录.这样的表将使数据库大小增加2-3个数量级(x10,x100).审计表将很快成为一切的瓶颈:

  • 每个DML操作都需要在审计表中进行锁定
  • 由于审计,所有管理和维护操作都必须适应数据库的大小

考虑架构更改.可以删除名为"Foo"的表,然后可以创建名为"Foo"的不同表.审计跟踪必须能够区分两个不同的对象.更好地使用缓慢变化的维度方法.

考虑有效删除审计记录的需要.当应用程序主题策略规定的保留期限到期时,您需要能够删除到期审计记录.现在看起来似乎不是什么大问题,但5年后,当第一个记录到期时,审计表已经增长到9.5TB,这可能是一个问题.

考虑需要查询审计.必须准备审计表结构,以便有效地响应审计查询.如果无法查询您的审核,那么它​​没有任何价值.查询将完全由您的要求驱动,只有您知道这些查询,但大多数审计记录是按时间间隔查询的("昨天晚上7点到8点之间发生了什么变化?"),按对象('此记录发生了什么变化) table?')或者作者('Bob在数据库中做了哪些更改?').


Igo*_*lov 19

我们正在使用ApexSQL Audit生成审计触发器,下面是此工具使用的数据结构.如果您不打算购买第三方解决方案,可以在试用模式下安装此工具,看看他们如何实现触发器和存储,然后为自己创建类似的东西.

我没有太多关于这些表如何工作的详细信息,但希望这会让你开始.

在此输入图像描述


no_*_*one 14

没有通用的方法可以按照您的方式进行.最终,您最终会为每个表编写大量代码.更不用说如果你需要比较每一栏的变化,它可能会很慢.

您可能同时更新多行这一事实意味着您需要打开游标以遍历所有记录.

我这样做的方法是使用与您正在跟踪的表格相同的表格,稍后将其取消以显示哪些列实际已更改.我还会跟踪实际进行更改的会话.这假设您在要跟踪的表中有主键.

所以给了这样一张桌子

CREATE TABLE TestTable  
(ID INT NOT NULL CONSTRAINT PK_TEST_TABLE PRIMARY KEY,
Name1 NVARCHAR(40) NOT NULL,  
Name2 NVARCHAR(40))
Run Code Online (Sandbox Code Playgroud)

我会在审计schmea中创建一个这样的审计表.

CREATE TABLE Audit.TestTable  
(SessionID UNIQUEIDENTIFER NOT NULL,  
ID INT NOT NULL,
Name1  NVARCHAR(40) NOT NULL,  
Name2  NVARCHAR(40),  
Action NVARCHAR(10) NOT NULL CONSTRAINT CK_ACTION CHECK(Action In 'Deleted','Updated'),  
RowType NVARCHAR(10) NOT NULL CONSTRAINT CK_ROWTYPE CHECK (RowType in 'New','Old','Deleted'),  
ChangedDate DATETIME NOT NULL Default GETDATE(),  
ChangedBy SYSNHAME NOT NULL DEFAULT USER_NAME())
Run Code Online (Sandbox Code Playgroud)

像这样的Update触发器

CREATE Trigger UpdateTestTable ON DBO.TestTable FOR UPDATE AS  
BEGIN  
    SET NOCOUNT ON
    DECLARE @SessionID UNIQUEIDENTIFER
    SET @SessionID = NEWID()
    INSERT Audit.TestTable(Id,Name1,Name2,Action,RowType,SessionID)
    SELECT ID,name1,Name2,'Updated','Old',@SessionID FROM Deleted

    INSERT Audit.TestTable(Id,Name1,Name2,Action,RowType,SessionID)
    SELECT ID,name1,Name2,'Updated','New',@SessionID FROM Inserted

END
Run Code Online (Sandbox Code Playgroud)

这运行得非常快.在报告期间,您只需基于sessionID和主键加入行并生成报告.或者,您可以拥有一个批处理作业,该作业定期遍历审计表中的所有表,并准备一个显示更改的名称 - 值对.

HTH