Sql server 如何跟踪由Microsoft SQL Server中的存储过程引起的更改流?

Sql server 如何跟踪由Microsoft SQL Server中的存储过程引起的更改流?,sql-server,tsql,audit,Sql Server,Tsql,Audit,使用下表: CREATE TABLE [Test] ( [Id] BIGINT IDENTITY NOT NULL, [Name] CHARACTER VARYING(255) NOT NULL, [Description] CHARACTER VARYING(MAX) NOT NULL, PRIMARY KEY([Id]) ); 我使用存储过程控制新记录的创建: CREATE PROCEDURE [Test_Create] @SessionId BI

使用下表:

CREATE TABLE [Test]
(
    [Id] BIGINT IDENTITY NOT NULL,
    [Name] CHARACTER VARYING(255) NOT NULL,
    [Description] CHARACTER VARYING(MAX) NOT NULL,

    PRIMARY KEY([Id])
);
我使用存储过程控制新记录的创建:

CREATE PROCEDURE [Test_Create]
    @SessionId BINARY(32),
    @Name CHARACTER VARYING(255),
    @Description CHARACTER VARYING(MAX)
AS
BEGIN
    BEGIN TRANSACTION;
        BEGIN TRY
            INSERT INTO [Test] ([Name], [Description])
            VALUES (@Name, @Description);
        END TRY
        BEGIN CATCH
            ROLLBACK TRANSACTION;
            THROW;
        END CATCH
    COMMIT TRANSACTION;
END
我有一个触发器,它只记录这个表的before和after值,用于所有更改。调用我的存储过程时,将触发此触发器并记录到另一个表。但是,我的触发器显然不能使用
@SessionId
变量来记录哪个网站用户会话导致web服务器上运行的SQL客户端调用存储过程。我不想使用
SET CONTEXT\u INFO
,因为它在连接池和并行执行计划中是不稳定的

也就是说,我想我可以将传递到存储过程的
@SessionId
@@SPID
值关联起来,但这对于连接池来说还是有点棘手。据我所知,这是行不通的

假设我有一个唯一的会话号传入存储过程,我如何跟踪我的网站上的哪个用户对我的任何表进行了特定的更改

如果他们调用存储过程,我需要知道调用的存储过程以及它如何更改表(前后值)

是否有其他方法可以检索以下信息并将它们链接在一起以形成审计跟踪

  • 导致调用存储过程的网站用户/会话
  • 调用的存储过程及其参数
  • 结果数据查询
  • 查询的效果(数据前后)
    • 我的第一个问题是“为什么”

      基于您的潜在答案,有几个选项:

      若您只是好奇,并想对某个问题进行一些调查,那个么可以使用SQL Server探查器或数据库引擎跟踪捕获和跟踪重播,并使用正确的日志记录事件。这将准确地告诉您调用了哪些过程、为什么调用以及使用了正确的参数

      如果您想立即将此信息用于管理报告,我建议您将其传递到存储过程中,并将其存储在表中,以便根据需要查询它


      如果你想在将来某个时候使用这些信息,您可以围绕数据访问层打开日志记录,以将查询前后的信息存储在日志文件中,如果您确实愿意,也可以再次存储在数据库中。

      我建议您修改表结构,以便将
      @SessionId
      值存储在表中以供创建和修改

      我有一个ASP.Net应用程序,它还必须记录所有更改以进行审核,并且需要审核的表都有

      CreatedDateTime DateTime NOT NULL
      CreatedBy nvarchar(50) NOT NULL
      ModifiedDateTime DateTime NULL
      ModifiedBy nvarchar(50) NULL
      
      纵队

      用户使用Windows身份验证登录,我们将用户的
      domain\username
      传递给所有存储的进程,以便将其存储在
      CreatedBy
      ModifiedBy
      列中。
      CreatedDateTime
      /
      ModifiedDateTime
      值由存储的进程设置

      我们的更改日志审核是通过CLR触发器完成的,该触发器只提取新记录上的
      修改值,并将其作为进行更改的人员记录


      我认为,使用@SessionId值也能很好地工作。

      您不能只将日志添加到
      Test\u Create
      本身?@David如果我这样做,那么我需要为每次插入、更新或删除写入日志项,然后还要找出旧值是什么。这将添加大量额外的代码,这些代码可以通过触发器解决。我认为最好是弄清楚如何将存储过程上下文中的
      @SessionId
      与触发器上下文中的
      @@SPID
      关联起来。目的是为了安全审核和恢复。我们需要知道我们网站上的哪个用户更改了一些数据。我们正在尝试为恶意用户删除大量内容时构建恢复功能,我们需要暂停用户,然后仅回滚他们所做的操作,并捕获crossfire中的任何合法编辑/添加。我们希望在数据库中控制尽可能多的数据的原因是因为我们已经分散了这个系统的各个部分;许多受信任的客户端连接到SQL Server实例并代表其用户群进行更改。在这种情况下,我将使用上面的中间选项。为可用于回滚更改的表创建审核表。有很多方法可以做到这一点。可以使用审计表镜像表结构,但这是非常脆弱的。您可以创建一个更通用的结构,并通过触发器进行更新,例如属性(ID、名称、描述)、属性更改(ID、PropertyIdChanged、UserId、日期更改、ValueBefore、ValueAfter)。这对于审计很好,但使用它恢复数据需要仔细考虑。可能还有其他解决方案!因此,我尝试了触发器方法并添加了属性更改等等。我甚至让它向后滚动。我发现使用触发器的困难在于,我无法将
      @SessionId
      与触发器通信,除非使用我在问题中提到的
      SET CONTEXT\u INFO
      。而不是使用触发器,在存储过程中执行insert,然后就可以将sessionid存储在审计表中,而不必弄脏主数据表。当UserA修改记录,然后UserB修改记录时会发生什么情况?您的设计不支持审核跟踪,只支持“最新”的方法。抱歉,我不清楚。虽然实际表仅显示最后一个更改记录的人(这对于显示目的很有用),但审核触发器通过记录用户/更改日期/表名/字段名/旧值/新值将更改的每个字段记录到单独的审核数据库/表中。因此,如果用户在一次更新中更改了20个字段,那么日志表将有20行显示发生了什么