删除“登录表”中的许多记录后,服务器登录触发器失败 -SQL 错误 2801

Man*_*ion 5 trigger sql-server-2008 sql-server

我们定义了一个服务器登录触发器,用于记录每次登录,并在表中记录诸如 windows/sql 用户名、客户端和时间等信息。

该表没有聚集索引,但它有一个“PK_ID”列,它是 bigint 和自动增量。

上周,我们从“登录表”中总共 9000 万条记录中删除了大约 8000 万条记录(带有delete from......,我们没有truncate该表)。

但从那以后我们看到登录触发器失败的多种情况

由于触发器执行,登录 'SQL\xy' 登录失败。
将数据库上下文更改为“master”。
(Microsoft SQL Server,错误:17892)

我们确实重新启动了整个 Windows 服务器几次,之后错误消失了几个小时,但似乎时不时地回来。请注意,这仅在我们删除了这么多记录后才开始出现。

我们发现在用户无法登录之前,我们收到以下错误:

消息 2801,级别 16,状态 1,: 
对象“my_proc”的定义自编译以来已更改。

之后,我们得到了如上所述的错误 17892。

有谁知道可能是什么问题?

触发器定义

    SET ANSI_NULLS ON

    GO

    SET QUOTED_IDENTIFIER ON

    GO

    CREATE TRIGGER [Tr_My_Logon]
     ON ALL SERVER  WITH EXECUTE AS 'xy'
     FOR LOGON
     AS
     BEGIN
        BEGIN TRY
            INSERT INTO mydatabase.myschema.myLogonHistoryTable
                SELECT GETDATE(),
                      ORIGINAL_LOGIN(),
                      EVENTDATA().value('(/EVENT_INSTANCE/LoginType)[1]', 'varchar(500)'),
                      @@SPID,
                      program_name(),
                      HOST_NAME(),
                      EVENTDATA().value('(/EVENT_INSTANCE/ClientHost)[1]', 'varchar(500)')
       END TRY

       BEGIN CATCH
           PRINT ERROR_MESSAGE()
       END CATCH

     END
    GO

    SET ANSI_NULLS OFF

    GO

    SET QUOTED_IDENTIFIER OFF

    GO
Run Code Online (Sandbox Code Playgroud)

Mat*_*tum -1

从日志记录的角度来看,如果您打算从表中删除超过 50% 的行,则应使用以下方法:

\n\n
    \n
  • 将事务隔离级别设置为可序列化
  • \n
  • 开始交易
  • \n
  • 创建一个新表,命名与原表相同,后缀为_x\ns
  • \n
  • 将要保留的结果从原始表复制到 _x\none
  • \n
  • 删除原来的表
  • \n
  • 将 _x 表重命名回原始表
  • \n
  • 提交交易
  • \n
\n\n

另外,您描述的 PK_ID 列应该是表的 PK 和聚集索引,否则它只是一个堆。

\n\n

另外,就记录服务器登录而言,也许您使用审核或扩展事件会话会运气更好?

\n\n

您描述的“对象 \xe2\x80\x98my_proc\xe2\x80\x99 的定义自编译以来已更改”错误应该可以通过调用 sp_recompile 来解决。

\n