How can I track the flow of a change caused by a stored procedure in Microsoft SQL Server?

StackOverflow https://stackoverflow.com/questions/23375580

  •  12-07-2023
  •  | 
  •  

Question

With the following table:

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

    PRIMARY KEY([Id])
);

I control creation of new records with the stored procedure:

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

I have a trigger that simply logs the before and after values for this table, for all changes. When my stored procedure is called, this trigger is fired and logs to another table. However, my trigger obviously cannot have the @SessionId variable to log which website user session caused the stored procedure to be invoked by the SQL client running on a web server. I do not want to use SET CONTEXT_INFO because it is unstable with connection pooling and parallel execution plans.

That said, I thought I could correlate the @SessionId passed in to the stored procedure with the @@SPID value, but again this is a little tricky with connection pooling. It won't work, as far as I can tell.

How can I track which user on my website, assuming I have a unique session number for them passed into my stored procedure, caused specific changes to any of my tables?

If they invoke a stored procedure, I need to know the stored procedure invoked and how it altered the tables (before and after values).

Is there perhaps an alternative to retrieve the following information and link them together to form an audit trail?

  • The website user/session that caused a stored procedure to be invoked
  • The stored procedure that was invoked and its parameters
  • The resultant data queries
  • The effects of the queries (before and after data)
Était-ce utile?

La solution

I would recommend that you modify your table structure so that the @SessionId value is stored in the table for creation and modification.

I have an ASP.Net app that also must log all changes for auditing purposes, and the tables that require auditing all have

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

columns

Users log in with Windows Authentication, and we pass the user's domain\username to all the stored procs so that it can be stored in the CreatedBy or ModifiedBy col. The CreatedDateTime/ModifiedDateTime values are set by the stored procs.

Our change log auditing is done by a CLR trigger which just extracts the ModifiedBy value on the new record and this is logged as the person making the change.

Using your @SessionId value would work just as well I would think.

Autres conseils

My first question is "why"?

A few options based on your potential answer:

If you are just curious and want to do some investigation into a problem you can use SQL Server Profiler or Database Engine Trace Capture and Trace Replay with the correct logging events. This will tell you exactly which procedures have been called, by why user and with the correct parameters.

If you want to use this information immediately for management reporting, I suggest you pass it into your stored procedures and store it in a table so you can interrogate it as needed.

If you want to use this information at some point in the future, you could turn logging on around your data access layer to store the information before and after your query either in a log file or again in the database if you really want to.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top