【问题标题】:Guarantee T-SQL Stored Procedure INSERTs before SELECT?保证 T-SQL 存储过程在 SELECT 之前插入?
【发布时间】:2011-06-17 21:40:16
【问题描述】:

我有一个从 SQL Server 2008 数据库中检索敏感信息的存储过程。我想修改该过程,以便在任何时候调用它时,它都会在单独的表中记录有关谁调用它的信息。

我认为类似以下的方法会起作用:

declare @account varchar(255);
set @account = (SELECT SYSTEM_USER);

INSERT into AUDIT_LOG(ACCOUNT, TSTAMP)
VALUES(@account, getdate())
;

--Now fetch data
SELECT x,y,z from sensitive_info;

我的问题是客户端应用程序可以调用此存储过程并获取敏感信息,但提交连接并且永远不会发生 INSERT!

有没有办法强制 INSERT 在 SELECT 之前发生?

我使用的是 SQL Server 2008。

谢谢, 卡尔

【问题讨论】:

    标签: tsql sql-server-2008


    【解决方案1】:

    只有在事务已启动时才提交。

    因此,您可以先测试打开的事务并禁止读取。这将确保没有事务可以回滚。我在这里使用了 XACT_STATE()

    同时使用 SET XACT_ABORT ON 和 TRY/CATCH 意味着用于记录的 INSERT 必须在读取发生之前也发生。 INSERT 上的任何错误根本都将转到 CATCH 块。所以没有读取和日志记录失败本身也可以被记录。

    所以:这是您对“登录时只读”的保证

    显式事务没有帮助:INSERT 无论如何都是原子操作。如果被调用者打开一个事务,则日志条目可以回滚

    CREATE PROC getSecretStuff
    AS
    SET NOCOUNT, XACT_ABORT ON;
    
    BEGIN TRY
        IF XACT_STATE() <> 0
           RAISERRROR ('Call not allowed in an active transaction', 16, 1)
    
        INSERT into AUDIT_LOG(ACCOUNT, TSTAMP)
        VALUES(SYSTEM_USER, getdate());
    
        --Now fetch data
        SELECT x,y,z from sensitive_info;
    
    END TRY
    BEGIN CATCH
        --     error handling etc
    END CATCH
    GO
    

    【讨论】:

    • 谢谢,这行得通。我的特殊问题有点复杂,因为我使用 Python 的 adodbapi 模块作为客户端,它会自动启动一个事务,但我发现了一个 hack 来禁用它。您的解决方案运行良好,因为如果客户端不遵守规则,服务器将不会显示数据。
    【解决方案2】:

    为什么不使用build in auditing functionality

    【讨论】:

    • 我最初看过这个,但审计信息似乎不能存储在数据库表中。我不确定那里的基本原理是什么,但我并不觉得对 Windows 事件日志卑躬屈膝很有趣。不过,我可能会将它与另一种方法结合使用。
    【解决方案3】:

    您是否尝试过使用显式事务并在提交语句之后进行选择?

    【讨论】:

    • 我尝试了显式事务,但没有得到预期的结果。我认为敏感数据仍然提供,但我必须回去验证。
    • 我仔细检查了——尽管将 INSERT 和 SELECT 包装在 BEGIN TANSACTION / COMMIT TRANSACTION 中,但当客户端未提交时,该行从未插入。有趣的是该表有一个标识列,下一次插入到表中did跳过了序列中的一个数字。
    【解决方案4】:

    在表中插入记录时,您应该能够获得 ast 插入值的 SCOPE_IDENTITY()。在从 sensitive_info 中选择 x,y,z 之前;您可以检查 SCOPE_IDENTITY() > 0 是否只执行 SELECT 语句。

    【讨论】:

    • 这似乎是个好主意,但我尝试了它并没有按预期工作。如果您在下面查看我的 cmets,似乎身份值正在增加,但是如果没有客户端的明确提交,则永远不会插入该行。
    猜你喜欢
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    相关资源
    最近更新 更多