WSUS всегда был проклятием для каждого ИТ-администратора. Сколько потоков вы найдете с одной и той же проблемой - сбой мастера очистки сервера. Текст ниже работал для меня.
Я пробовал множество SQL-скриптов как от Microsoft, так и из общедоступных источников, и все они давали неоднозначные результаты. На прошлой неделе наш сервер WSUS снова начал кашлять меховыми комками, поэтому я заплатил деньги и создал тикет в службу поддержки. Приведенный ниже текст в точности соответствует полученному от службы поддержки MS. Шаг 8, в моем случае, занял полтора дня, и даже с некоторыми ошибками. Я проигнорировал эти ошибки. Шаг 9 был быстрым, но и с парой ошибок. Я также проигнорировал эти ошибки (ошибки взаимоблокировки). После завершения я повторно запустил мастер очистки сервера, и он работал отлично. Все они были запущены в среде SQL Server Management Studio и с использованием WID.
Это не вопрос, а моя цель — попытаться помочь другим администраторам решить эти хронические проблемы с WSUS. Ваш пробег может быть очень большим - я надеюсь, что это поможет некоторым из вас.
Пожалуйста, следуйте указанным ниже шагам:
--------------------------------------------- --------------------------------------------- ----------------------------------------
1) Переиндексация:
ИСПОЛЬЗОВАТЬ ЮСДБ;
ИДТИ
УСТАНОВИТЬ БЕЗ СЧЕТА;
-- Перестроить или реорганизовать индексы на основе уровней их фрагментации.
ЗАЯВИТЕ ТАБЛИЦУ @work_to_do (
объектный идентификатор
, индекс int
, плавающая плотность страницы
, поплавок фрагментации
, числовое значение
)
ОБЪЯВИТЬ @objectid int;
ОБЪЯВИТЬ @indexid int;
DECLARE @schemaname nvarchar(130);
DECLARE @objectname nvarchar(130);
DECLARE @indexname nvarchar(130);
DECLARE @numrows int
DECLARE @density float;
DECLARE @fragmentation float;
ОБЪЯВИТЬ @command nvarchar(4000);
DECLARE бит @fillfactorset
DECLARE @numpages int
-- Выберите индексы, которые необходимо дефрагментировать, на основе следующих
-- * Низкая плотность страницы
-- * Внешняя фрагментация высока по отношению к размеру индекса
PRINT 'Оценка фрагментации: Начало. ' + конвертировать (nvarchar, getdate(), 121)
ВСТАВЬТЕ @work_to_do
ВЫБРАТЬ
f.object_id
, index_id
, avg_page_space_used_in_percent
, avg_fragmentation_in_percent
, количество_записей
ОТ
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'SAMPLED') AS f
КУДА
(f.avg_page_space_used_in_percent < 85,0 и f.avg_page_space_used_in_percent/100,0 * page_count < page_count - 1)
или (f.page_count > 50 и f.avg_fragmentation_in_percent > 15,0)
или (f.page_count > 10 и f.avg_fragmentation_in_percent > 80,0)
PRINT 'Количество индексов для перестроения: ' + cast(@@ROWCOUNT as nvarchar(20))
PRINT 'Оценка фрагментации: Конец. ' + конвертировать (nvarchar, getdate(), 121)
ВЫБЕРИТЕ @numpages = сумма (ps.used_page_count)
ОТ
@work_to_do КАК ФАЙ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.indexes AS i ON fi.objectid = i.object_id и fi.indexid = i.index_id
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.dm_db_partition_stats AS ps на i.object_id = ps.object_id и i.index_id = ps.index_id
-- Объявить курсор для списка обрабатываемых индексов.
ОБЪЯВИТЬ curIndexes CURSOR FOR SELECT * FROM @work_to_do
-- Откройте курсор.
ОТКРЫТЬ
-- Цикл по индексам
ПОКА (1=1)
НАЧИНАТЬ
ПОЛУЧИТЬ СЛЕДУЮЩИЙ ОТ curIndexes
INTO @objectid, @indexid, @density, @fragmentation, @numrows;
ЕСЛИ @@FETCH_STATUS < 0 BREAK;
ВЫБРАТЬ
@objectname = QUOTENAME(o.name)
, @schemaname = QUOTENAME(s.name)
ОТ
sys.objects КАК o
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.schemas as s ON s.schema_id = o.schema_id
КУДА
о.object_id = @objectid;
ВЫБРАТЬ
@indexname = QUOTENAME(имя)
, @fillfactorset = CASE fill_factor WHEN 0 THEN 0 ELSE 1 END
ОТ
sys.indexes
КУДА
object_id = @objectid AND index_id = @indexid;
ЕСЛИ ((@density МЕЖДУ 75,0 И 85,0) И @fillfactorset = 1) ИЛИ (@фрагментация < 30,0)
SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';
ИНАЧЕ, ЕСЛИ @numrows >= 5000 И @fillfactorset = 0
SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' ПЕРЕСТРОЙТЕ С (FILLFACTOR = 90)';
ЕЩЕ
SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';
PRINT convert(nvarchar, getdate(), 121) + N' Выполнение: ' + @command;
ВЫПОЛНИТЬ (@команда);
PRINT convert(nvarchar, getdate(), 121) + N' Done.';
КОНЕЦ
-- Закройте и освободите курсор.
ЗАКРЫТЬ
УДАЛИТЬ curIndexes;
ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ * ОТ @work_to_do)
НАЧИНАТЬ
PRINT 'Приблизительное количество страниц в фрагментированных индексах: ' + cast(@numpages as nvarchar(20))
ВЫБЕРИТЕ @numpages = @numpages - сумма (ps.used_page_count)
ОТ
@work_to_do КАК ФАЙ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.indexes AS i ON fi.objectid = i.object_id и fi.indexid = i.index_id
ВНУТРЕННЕЕ СОЕДИНЕНИЕ sys.dm_db_partition_stats AS ps на i.object_id = ps.object_id и i.index_id = ps.index_id
PRINT 'Приблизительное количество освобожденных страниц: ' + cast(@numpages as nvarchar(20))
КОНЕЦ
ИДТИ
--Обновить всю статистику
PRINT 'Обновление всей статистики.' + конвертировать (nvarchar, getdate(), 121)
EXEC sp_updatestats
PRINT 'Завершено обновление статистики.' + конвертировать (nvarchar, getdate(), 121)
ИДТИ
--------------------------------------------- ---------------------------------------------
2) Запустите приведенный ниже запрос, чтобы получить количество замененных обновлений.
ВЫБЕРИТЕ ID обновления из vwMinimalUpdate, ГДЕ IsSuperseded = 1 И отклонено = 0
--------------------------------------------- ------------------------------------
3) Запустите приведенный ниже запрос, чтобы удалить все замененные обновления и запустить мастер очистки сервера.
DECLARE @var1 уникальный идентификатор
ОБЪЯВИТЬ @msg nvarchar(100)
ОБЪЯВИТЬ Курсор DU
ЗА
ВЫБЕРИТЕ ID обновления из vwMinimalUpdate, ГДЕ IsSuperseded = 1 И отклонено = 0
Открыть ДД
ПОЛУЧИТЬ СЛЕДУЮЩИЙ ИЗ DU В @var1
ПОКА (@@FETCH_STATUS > -1)
НАЧИНАТЬ
RAISERROR(@msg,0,1) WITH NOWAIT exec spDeclineUpdate @updateID=@var1,@adminName=N'domain\user',@failIfReplica=1
ПОЛУЧИТЬ СЛЕДУЮЩИЙ ИЗ DU В @var1
КОНЕЦ
ЗАКРЫТЬ ДУ
ОСВОБОДИТЬ DU
--------------------------------------------- -------------------------------------
4) Запустите следующий SQL-запрос на SQL к базе данных SUSDB, чтобы получить количество обновлений для очистки:
exec spGetObsoleteUpdatesToCleanup
--------------------------------------------- --------------------------------------
5) Запустите приведенный ниже запрос в базе данных SQL, чтобы удалить обновления, а затем запустите мастер очистки сервера:
ОБЪЯВИТЬ @var1 INT
ОБЪЯВИТЬ @msg nvarchar(100)
СОЗДАТЬ ТАБЛИЦУ #results (Col1 INT)
ВСТАВИТЬ В #results(Col1) EXEC spGetObsoleteUpdatesToCleanup
ОБЪЯВИТЬ WC Курсор
ЗА
ВЫБЕРИТЕ Col1 ИЗ #results
ОТКРЫТЫЙ ТУАЛЕТ
ПОЛУЧИТЬ СЛЕДУЮЩУЮ ИЗ ТУАЛЕТА
ВНУТРИ @var1
ПОКА (@@FETCH_STATUS > -1)
BEGIN SET @msg = 'Удаление' + CONVERT(varchar(10), @var1)
RAISERROR(@msg,0,1) С NOWAIT EXEC spDeleteUpdate @localUpdateID=@var1
FETCH NEXT FROM WC INTO @var1 END
ЗАКРЫТЬ ТУАЛЕТ
УДАЛИТЬ ТУАЛЕТ
УДАЛИТЬ ТАБЛИЦУ #results
--------------------------------------------- ----------------------------------------
6) Запустите приведенный ниже запрос, чтобы узнать нет. обновлений для XML длиной 5000 и более:
Выбрать
u.UpdateID,
r.RevisionNumber,
р.RevisionID,
lp.Title,
pr.ExplicitlyDeployable как ED,
пр.UpdateType,
pr.CreationDate
от
tbОбновить
внутреннее соединение tbRevision r на u.LocalUpdateID = r.LocalUpdateID
внутреннее соединение tbProperty pr на pr.RevisionID = r.RevisionID
внутреннее соединение tbLocalizedPropertyForRevision lpr на r.RevisionID = lpr.RevisionID
внутреннее соединение tbLocalizedProperty lp на lpr.LocalizedPropertyID = lp.LocalizedPropertyID
куда
lpr.LanguageID = 1033
и r.RevisionID в (
Выбрать
t1.RevisionID
от
tbBundleAll t1
внутреннее соединение tbBundleAtLeastOne t2 на t1.BundledID=t2.BundledID
куда
t2.RevisionID in(SELECT dbo.tbXml.RevisionID FROM dbo.tbXml
ВНУТРЕННЕЕ СОЕДИНЕНИЕ dbo.tbProperty ON dbo.tbXml.RevisionID = dbo.tbProperty.RevisionID
где ISNULL (длина данных (dbo.tbXml.RootElementXmlCompressed), 0) > 50000) и ishidden = 0 и pr.ExplicitlyDeployable = 1)
--------------------------------------------- ---------------------------------------------
7) Если есть обновления, мы отклоняем их с помощью следующего курсора:
ОБЪЯВИТЬ @UpdateID nvarchar(100)
ОБЪЯВИТЬ @msg nvarchar(100)
CREATE TABLE #Updates (UpdateID nvarchar(100))
ВСТАВИТЬ В #Updates(UpdateID)
Выбрать
u.UpdateID
от
tbОбновить
внутреннее соединение tbRevision r на u.LocalUpdateID = r.LocalUpdateID
внутреннее соединение tbProperty pr на pr.RevisionID = r.RevisionID
внутреннее соединение tbLocalizedPropertyForRevision lpr на r.RevisionID = lpr.RevisionID
внутреннее соединение tbLocalizedProperty lp на lpr.LocalizedPropertyID = lp.LocalizedPropertyID
куда
lpr.LanguageID = 1033
и r.RevisionID в (
Выбрать
t1.RevisionID
от
tbBundleAll t1
внутреннее соединение tbBundleAtLeastOne t2 на t1.BundledID=t2.BundledID
куда
t2.RevisionID in(SELECT dbo.tbXml.RevisionID FROM dbo.tbXml
ВНУТРЕННЕЕ СОЕДИНЕНИЕ dbo.tbProperty ON dbo.tbXml.RevisionID = dbo.tbProperty.RevisionID
где ISNULL (длина данных (dbo.tbXml.RootElementXmlCompressed), 0) > 50000) и ishidden = 0 и pr.ExplicitlyDeployable = 1)
ОБЪЯВИТЬ Курсор UC
ЗА
ВЫБЕРИТЕ ID обновления из #Updates
ОТКРЫТЬ UC
ПОЛУЧИТЬ СЛЕДУЮЩУЮ ИЗ UC
В @UpdateID
ПОКА(@@FETCH_STATUS > -1)
BEGIN SET @msg = 'Отклонение' + @UpdateID
RAISERROR(@msg,0,1) С NOWAIT EXEC spDeclineUpdate @updateID=@UpdateID,@adminName=N'mach14\administrator',@failIfReplica=1
ПОЛУЧИТЬ СЛЕДУЮЩИЙ ИЗ UC В @UpdateID END
ЗАКРЫТЬ
ОСВОБОДИТЬ UC
УДАЛИТЬ ТАБЛИЦУ #Обновления
--------------------------------------------- --------------------------------------------
8) Отказ от обновлений драйверов: -
ИСПОЛЬЗОВАТЬ ЮСДБ
ИДТИ
ВЫБЕРИТЕ UpdateTypeID ИЗ tbUpdateType, ГДЕ Имя = «Драйвер»
ИДТИ
удалить из tbrevisionlanguage, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbProperty, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbLocalizedPropertyForRevision, где идентификатор ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId в (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbFileForRevision, где идентификатор ревизии (выбрать идентификатор ревизии из tbRevision, где LocalUpdateId в (выбрать LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbInstalledUpdateSufficientForPrerequisite, где Prerequisiteid в (выбрать Prerequisiteid из tbPreRequisite, где id ревизии (выбрать id ревизии из tbRevision, где LocalUpdateId в (выбрать LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbPreRequisite, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbDeployment, где находится номер ревизии (выберите идентификатор версии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbXml, где находится номер ревизии (выберите номер ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbPreComputedLocalizedProperty, где идентификатор ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId в (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbDriver, где находится номер ревизии (выберите номер ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbFlattenedRevisionInCategory, где идентификатор ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId в (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbRevisionInCategory, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbMoreInfoURLForRevision, где идентификатор ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId в (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'))
удалить из tbRevision, где LocalUpdateId (выбрать LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629')
удалить из tbUpdateSummaryForAllComputers, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629')
удалить из tbUpdate, где UpdateTypeID = 'D2CB599A-FA9F-4AE9-B346-94AD54EE0629'
9) Удалить скрытые обновления:
ВЫБЕРИТЕ * ИЗ tbUpdate, ГДЕ isHidden = 1
Â
удалить из tbrevisionlanguage, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbProperty, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId в (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbLocalizedPropertyForRevision, где идентификатор ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId в (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbFileForRevision, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden=1))
удалить из tbInstalledUpdateSufficientForPrerequisite, где Prerequisiteid в (выбрать Prerequisiteid из tbPreRequisite, где id ревизии в (выбрать id ревизии из tbRevision, где LocalUpdateId в (выбрать LocalUpdateId из tbUpdate, где ishidden = 1)))
удалить из tbPreRequisite, где находится ревизия (выберите ревизию из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden=1))
удалить из tbDeployment, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden=1))
удалить из tbXml, где находится номер ревизии (выберите номер ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden=1))
удалить из tbPreComputedLocalizedProperty, где идентификатор ревизии (выбрать идентификатор ревизии из tbRevision, где LocalUpdateId (выбрать LocalUpdateId из tbUpdate, где ishidden=1))
удалить из tbDriver, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbFlattenedRevisionInCategory, где идентификатор ревизии (выбрать идентификатор ревизии из tbRevision, где LocalUpdateId в (выбрать LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbRevisionInCategory, где находится номер ревизии (выбрать идентификатор ревизии из tbRevision, где LocalUpdateId в (выбрать LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbMoreInfoURLForRevision, где идентификатор ревизии (выбрать идентификатор ревизии из tbRevision, где LocalUpdateId в (выбрать LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbBundleAtLeastOne, где находится пакет (выберите пакетный идентификатор из tbBundleAll, где номер ревизии (выберите номер ревизии из tbRevision, где LocalUpdateId в (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbBundleAll, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbSecurityBulletinForRevision, где находится номер ревизии (выбрать номер ревизии из tbRevision, где LocalUpdateId (выбрать LocalUpdateId из tbUpdate, где ishidden=1))
удалить из tbKBArticleForRevision, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbRevisionSupersedesUpdate, где находится номер ревизии (выберите идентификатор ревизии из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbBundleAtLeastOne, где находится ревизия (выберите ревизию из tbRevision, где LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbEulaProperty, где находится ревизия (выбрать ревизию из tbRevision, где LocalUpdateId (выбрать LocalUpdateId из tbUpdate, где ishidden = 1))
удалить из tbRevision, где находится LocalUpdateId (выберите LocalUpdateId из tbUpdate, где ishidden=1)
удалить из tbUpdateSummaryForAllComputers, где LocalUpdateId (выбрать LocalUpdateId из tbUpdate, где ishidden=1)
удалить из tbInstalledUpdateSufficientForPrerequisite, где LocalUpdateId (выбрать LocalUpdateId из tbUpdate, где ishidden=1)
удалить из tbUpdate, где ishidden = 1
--------------------------------------------- --------------------------------------------- --------------------------
Затем откройте консоль WSUS и перейдите в «Параметры\Мастер очистки сервера».
И запускайте мастера один за другим.