我们正在通过索引系统运行数据库维护,索引因锁定而失败?

4 index sql-server

我们一直在尝试在我们的系统中重新索引,在索引期间仍有用户使用数据库。在为某些表做索引时,索引失败,这似乎是由于死锁

我们使用的索引脚本是:

--------  REBUILDING THE INDEXES----------------------

CREATE TABLE #TableIDs (Tablename nvarchar(200),IndexName nvarchar(1000))
        --Database to be indexed--
        INSERT INTO #TableIDs (Tablename, IndexName) 
        SELECT a.object_id,name
        FROM sys.dm_db_index_physical_stats (DB_ID(N'RAL'), NULL, NULL, NULL, NULL) AS a
        JOIN sys.indexes AS b ON a.object_id = b.object_id AND a.index_id = b.index_id
        Where avg_fragmentation_in_percent > 20 and name is not null  and OBJECT_SCHEMA_NAME(a.object_id) = 'dbo' 
        And object_name(a.object_id) not in (SELECT
                                             OBJECT_NAME(p.object_id) BlockedObjectName
                                             FROM sys.dm_tran_locks AS tl
                                             INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id
                                             INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address
                                             INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
                                             INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
                                             INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
                                             CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
                                             CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
                                             Where db.name = 'RAL') 


declare c cursor for select object_name(Tablename) as Tablename ,IndexName from #TableIDs
declare @TableName varchar(1000)
declare @IndexName varchar(1000)
open c
fetch next from c into @TableName, @IndexName
        while @@FETCH_STATUS = 0
        BEGIN       



              if ((SELECT
                                         count(OBJECT_NAME(p.object_id)) BlockedObjectName
                                         FROM sys.dm_tran_locks AS tl
                                         INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id
                                         INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address
                                         INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
                                         INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
                                         INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
                                         CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
                                         CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
                                         Where db.name = 'RALMYT' and OBJECT_NAME(p.object_id) = @TableName) ) = 0      
                BEGIN
                    EXEC ('ALTER INDEX ' + @IndexName + ' ON ' + @TableName + ' REBUILD WITH (FILLFACTOR=90,STATISTICS_NORECOMPUTE = OFF,ONLINE=OFF,MAXDOP=8)')
                    PRINT 'Reindexing ' + @IndexName + ' on  ' + @TableName + ' table'
                END
     fetch next from c into @TableName, @IndexName
End         
CLOSE c
DEALLOCATE c    


DROP TABLE #TableIDs
Run Code Online (Sandbox Code Playgroud)

请让我知道..... 如何在索引时避免错误或失败

Jon*_*gel 7

如果要求是在让用户继续工作的同时重建索引,您会发现如果您不能进行在线索引重建(仅在企业版中可用),您会发现这非常具有挑战性,如果不是不可能的话。

实际上只有两种解决方案:

  • 使用在线索引重建。
  • Do indexREORGANIZE而不是REBUILD-- reorgs 总是在线操作,但可能不如重建那么好,并且相比之下可能运行得更慢。

无论如何,我强烈建议使用已经构建和测试过的解决方案,例如Ola Hallengren 的维护脚本,而不是滚动您自己的脚本,它将根据索引的当前碎片状态智能地维护您的索引。索引实际上可能并不需要一直重建。