SQL Server 2008 R2日志记录查询执行时间不正确

时间:2013-01-30 19:36:41

标签: sql-server sql-server-2008-r2

编辑:我添加了登录触发器的所有代码。

为什么在尝试检索查询运行所需的总时间时会得到一些不正确的结果?这是在SQL Server 2008 R2上的登录触发器的上下文中。

出于测试目的,我想粗略估计登录触发器运行所需的总时间。以下是结果的一小部分示例:

LogonId  AppId  TotalLogonTime (in MS)
 101      1        0
 253      2        3
 289      2        3
 985      1       -3
 325      1        0

总时间如何评估为负数?在迄今为止的230万次执行中,有25次执行时间为-3毫秒。这是代码:

CREATE trigger [trgAudit]
on all server
with execute as 'TriggerLogonUser'
for logon
as
begin
    set nocount on
    set transaction isolation level read committed

declare
     @LoginTime datetime
    ,@IsWindowsUser bit
    ,@TotalLogonTimeMS int
    ,@ClientNetAddress varchar(48)
    ,@MacAddress nchar(12)
    ,@CurrentUserId int -- UserNames
    ,@ApplicationId int
    ,@HonId int --HostName
    ,@LogonId int --Logon
    ,@MacId int -- MacAddress
    ,@CnaId int -- ClientNetAddress

begin try
    /*
    *** Get the login time, user type, mac address, and client net address  
    */
 select
      @LoginTime = getdate(),
      @IsWindowsUser = case
                          when len(nt_domain) = 0
                             then 0
                          else 1
                       end,
      @MacAddress = p.net_address,
      @ClientNetAddress = convert(varchar(48),connectionproperty('client_net_address'))
 from sys.sysprocesses p
 where 
      p.spid = @@spid

 /*
 *** Client Net Address
 */          
      select top 1
           @CnaId = CnaId
      from master.sysmaintenance.ClientNetAddress with(index(IX_CnaAddress))
      where @ClientNetAddress = CnaAddress

      --if the ip does not exist, insert it.
      if @CnaId is null
           begin
                insert master.sysmaintenance.ClientNetAddress(CnaAddress)
                     values (@ClientNetAddress)
                select @CnaId = @@identity
           end

 /*
 *** Applications
 */     
      select top 1
           @ApplicationId = AppId
      from master.sysmaintenance.Applications with(index(IX_AppName))
      where app_name() = AppName

      if @ApplicationId is null
           begin
                insert master.sysmaintenance.Applications (AppName)
                     values (app_name())
                select @ApplicationId = @@identity
           end

 /*
 *** HostName
 */     
      select top 1
           @HonId = HonId
      from master.sysmaintenance.HostName with(index(IX_HonName))
      where HonName = host_name()

      if @HonId is null
           begin
                insert master.sysmaintenance.HostName
                     values (host_name())

                select @HonId = @@identity
           end

 /*
 *** UserNames
 */     
      select top 1
           @CurrentUserId = UsnId
      from master.sysmaintenance.Usernames with(index(IX_UsnName))
      where UsnName = original_login()

      if @CurrentUserId is null
           begin
                insert master.sysmaintenance.Usernames
                     values (original_login())

                select @CurrentUserId = @@identity
           end

 /*
 *** MacAddress
 */     
      select top 1
           @MacId = MacId
      from master.sysmaintenance.MacAddress with(index(IX_MacAddress))
      where MacAddress = @MacAddress

      -- same logic is continued as in the applications
      if @MacId is null
           begin
                insert master.sysmaintenance.MacAddress (MacAddress)
                     values (@MacAddress)

                select @MacId = @@identity
           end

 /*
 *** Get the total logon time
 */     
 select @TotalLogonTimeMS = datediff(ms,@LoginTime, getdate())

  -- insert ids of the data gathered on the logon event into the logon table.


           insert master.sysmaintenance.Logon ( LogAppId,
                                                LogHonId,
                                                IsWindowsLogon,
                                                CurrentLogonId,
                                                LogonDatetime,
                                                LogCnaId,
                                                LogMacId,
                                                LogonTimeMS )
                values ( @ApplicationId,
                         @HonId,
                         @IsWindowsUser,
                         @CurrentUserId,
                         @LoginTime,
                         @CnaId,
                         @MacId,
                         @TotalLogonTimeMS
                       )
end try

begin catch
    print cast(error_number()    as nvarchar(11))
    print cast(error_severity()  as nvarchar(11))
    print cast(error_state()     as nvarchar(11))
    print cast(error_procedure() as nvarchar(126))
    print cast(error_line()      as nvarchar(11))
    print cast(error_message()   as nvarchar(2048))
end catch
end

以下是登录表的DDL:

CREATE TABLE [sysmaintenance].[Logon](
    [LogonId] [bigint] IDENTITY(1,1) NOT NULL,
    [LogAppId] [int] NULL,
    [LogHonId] [int] NULL,
    [LogMacId] [int] NULL,
    [LogCnaId] [int] NULL,
    [IsWindowsLogon] [bit] NULL,
    [CurrentLogonId] [int] NULL,
    [LogonDatetime] [datetime] NULL,
    [LogonTimeMS] [int] NULL
) ON [PRIMARY]

CREATE UNIQUE CLUSTERED INDEX [PK_Logon] ON [sysmaintenance].[Logon] 
(
    [LogonId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

感谢任何帮助或见解。

1 个答案:

答案 0 :(得分:1)

GETDATE()

  

将当前数据库系统时间戳记作为没有数据库时区偏移量的日期时间值返回。 此值派生自运行SQL Server实例的计算机的操作系统。

现在,考虑到计算机时钟漂移,我想如果计算机的时间得到纠正(手动或自动),两次连续调用GETDATE()报告的时间(不是单个查询)可能会倒退。所有日期时间方法最终都依赖于计算机的时钟。

遗憾的是,你并没有记录这些GETDATE()结果中的一个和时间,所以你可以看到它们是否都发生在同一个“时间”。