YourSQLDba低版本的一个Bug的浅析

帮人分析解决一个YourSQLDba备份报错问题,我的以为有点意思,顺手记录一下分析思路,大致解决思路以下:sql

 

首先,找到YourSQLDba做业YourSQLDba_FullBackups_And_Maintenance的报错邮件或者做业的错误日志信息,检查YourSQLDba出错的详细信息。数据库

 

YOURSQLDBA.MAINT.ShowHistoryErrors 96服务器

 

发现YourSQLDba在更新统计信息是遇到错误,以下所示app

 

<Exec>
  <ctx>yMaint.UpdateStats</ctx>
  <inf>update statistics selected</inf>
  <cmd>update statistics [model].[dbo].[ServiceBrokerQueue] WITH sample 100 PERCENT</cmd>
  <err>Error 2706, Severity 16, level 6 : Table 'ServiceBrokerQueue' does not exist.</err>
</Exec>

 

 

检查发现这个对象是queue,根本不是表,因此更新统计信息会出错。ide

 

clip_image001

 

那么YourSQLDba怎么会更新queue对象的统计信息呢?我首先检查了一下YourSQLDba的版本信息。当前数据库服务器上的YourSQLDba是至关老的一个版本了。而后我就去检查YourSQLDba的代码this

 

 

Exec YourSQLDba.Install.PrintVersionInfo
 
========================================
 
YourSQLDba version: 5.0.2 2012-06-12

 

YourSQLDba更新统计信息是经过[yMaint].[UpdateStats]来更新统计,因而检查代码,发现获取要更新统计信息的对象是经过下面脚本获取的。首先将要更新统计信息的对象放到临时表#TableNames中去,而后生成更新统计信息的脚本。spa

 

-- makes query boilerplate with replacable parameter identified by
-- labels between '<' et '>'
-- this query select table for which to perform update statistics
truncate table #TableNames
set @sql =
'
 set nocount on
 ;With
   TableSizeStats as
 (
 select 
   object_schema_name(Ps.object_id, db_id('<DbName>')) as scn --collate <srvCol>
 , object_name(Ps.object_id, db_id('<DbName>')) as tb --collate <srvCol>
 , Sum(Ps.Page_count) as Pg
From
  sys.dm_db_index_physical_stats (db_id('<DbName>'), NULL, NULL, NULL, 'LIMITED') Ps
Group by 
  Ps.object_id  
)
Insert into #tableNames (scn, tb, seq, sampling)
Select 
  scn
, tb
, row_number() over (order by scn, tb) as seq
, Case 
    When pg > 200001 Then '10'
    When Pg between 50001 and 200000 Then '20'
    When Pg between 5001 and 50000 Then '30'
    else '100'
  End  
From 
  TableSizeStats
where (abs(checksum(tb)) % <SpreadUpdStatRun>) = <seqStatNow>

 

这个脚本会将queue类型的对象也放入临时表,因此明显是个Bug,不过YourSQLDba后续的版本已经Fix掉这个Bug了。以下所示,后续的版本就加上条件过滤了,只获取表和视图的数据。因此遇到这个问题,只须要升级YourSQLDba的版本就行了日志

 

 

   

-- makes query boilerplate with replacable parameter identified by
-- labels between "<" et ">"
-- this query select table for which to perform update statistics
truncate table #TableNames
set @sql =
'
 Use [<DbName>]
 set nocount on
 ;With
   TableSizeStats as
 (
 select 
   object_schema_name(Ps.object_id) as scn --collate <srvCol>
 , object_name(Ps.object_id) as tb --collate <srvCol>
 , Sum(Ps.Page_count) as Pg
From
  sys.dm_db_index_physical_stats (db_id("<DbName>"), NULL, NULL, NULL, "LIMITED") Ps
Where (   OBJECTPROPERTYEX ( Ps.object_id , "IsTable" ) = 1
       Or OBJECTPROPERTYEX ( Ps.object_id , "IsView" ) = 1)
Group by 
  Ps.object_id  
)
Insert into #tableNames (scn, tb, seq, sampling)
Select 
  scn
, tb
, row_number() over (order by scn, tb) as seq
, Case 
    When Pg > 5000001 Then "0"
    When Pg between 1000001 and 5000000 Then "1"
    When Pg between 500001 and 1000000 Then "5"
    When pg between 200001 and 500000 Then "10"
    When Pg between 50001 and 200000 Then "20"
    When Pg between 5001 and 50000 Then "30"
    else "100"
  End  
From 
  TableSizeStats
where scn is not null and tb is not null and (abs(checksum(tb)) % <SpreadUpdStatRun>) = <seqStatNow>
相关文章
相关标签/搜索