Контролируем SQL репликацию…

Задача: Программно отследить проблемы возникающие при MS SQL репликации.

Отслеживать будем подписчиков:

subsc

После поиска в интернете нашел описание хп процедур, позволяющих получить информацию о репликации программным способом.

Для получения информации по подписчикам используется процедура sp_replmonitorhelpsubscription.

Процедура должна вызываться из базы distribution на сервере распространителе.

Описание процедуры можно посмотреть по ссылке выше, мы же используем следующие параметры при вызове

EXECUTE distribution.dbo.sp_replmonitorhelpsubscription null {издатель, null- все}, null { имя публикуемой базы, null — все}, null { имя публикации, null — все},0 {тип публикации, 0 — публикация транзакций}

Так же можно указать тип возвращаемых записей передав доп пораметр mode, н-р в нашел случае можно было поставить значение 1 — Возвращать подписки с ошибками, но мы оставим по умолчанию 0 — возвращать все.

Результирующий набор вернет нам много всего интересного, по меня заинтересовали только эти столбцы

status — Максимальное значение состояния, берущееся по всем агентам репликации, связанным с публикацией; принимает одно из следующих значений:
1 = запущен.
2 = выполнен.
3 = выполняется.
4 = бездействует.
5 = повтор.
6 = ошибка

monitorranking — Ранжирующее значение для упорядочивания подписок в результирующем наборе может быть одним из следующих.

Для публикаций транзакций:
60 = ошибка.
56 = предупреждение: критическое для производительности.
52 = предупреждение: срок действия скоро истекает или уже истек.
50 = предупреждение: подписка не инициализирована.
40 = попытка повторно выполнить команду, завершившуюся неудачно.
30 = не выполняется (завершено успешно).
20 = выполняется (запуск, выполнение или бездействие).

А отслеживать мы будем условия —
(status in (5,6) ) или ( monitorranking in (60,56,52,50,40))

Всё бы здорово, но вот есть одна проблема — как обработать результат выдаваемый хп ?

Я знаю только один способ, сделать insert into таблица execute хп.
Но он нам не подходит в данном случае, т.к. он имеет ограничение — не поддерживается вложенность, т.е. если внутри хп содержится такой же код, то мы получим ошибку.

В нашем случае так оно и есть, этот метод не будет работать.

После долгих поисков в инете нашел способ обхода проблемы, он конечно не очень, но вполне рабочий — мы выкидываем результат выполнения во внешний текстовой файл, а потом загружаем его назад и дальше с ним работаем. Для этого нам потребуется разрешение на выполнение в базе процеруды xp_cmdshell.

итак код:

-- создаём временную таблицу для результата
create table #ReplTemp(
status int,
warning int,
subscriber sysname,
subscriber_db sysname,
publisher_db sysname,
publication sysname,
publication_type int,
subtype int,
latency int,
latencythreshold int,
agentnotrunning int,
agentnotrunningthreshold int,
timetoexpiration int,
expirationthreshold int,
last_distsync datetime,
distribution_agentname sysname,
mergeagentname sysname,
mergesubscriptionfriendlyname sysname,
mergeagentlocation sysname,
mergeconnectiontype int,
mergePerformance int,
mergerunspeed float,
mergerunduration int,
monitorranking int,
distributionagentjobid binary(16),
mergeagentjobid binary(16),
distributionagentid int,
distributionagentprofileid int,
mergeagentid int,
mergeagentprofileid int,
logreaderagentname sysname)

declare @Command varchar(2000);
-- выполняем хп и сохраняем результат в тхт
SET @Command = 'bcp "EXECUTE distribution.dbo.sp_replmonitorhelpsubscription null,null,null,0 " queryout "l:\temp\result.txt"  -c  -U имя_юзера -P пароль_юзера';
EXEC xp_cmdshell @Command, NO_OUTPUT;
-- вставляем результат во временную таблицу
BULK INSERT #ReplTemp
FROM 'l:\temp\result.txt';
-- грохаем временный файлик
SET @Command = 'del l:\temp\result.txt';
EXEC xp_cmdshell @Command, NO_OUTPUT;

-- обрабатываем результат
set @Count=( select count(*) from #ReplTemp where (status in (5,6) )or ( monitorranking in (60,56,52,50,40)));
-- если есть проблемы, то что то делаем
if @Count>0
-- в моём случае, вставляем в таблицу, из которой потом идёт отправка почтовых уведомлений
insert into SendMail (email, subject,text, source)
values ('админ@домен.ру',
'Проблемы SQL Репликации',
'глючных заданий - '+cast(@Count as varchar(5)),'check_repl');

Далее втыкаем эту процедуру в job, который будет выполняться, ну например раз в полчаса и тихо радуемся результату.

Способ далеко не идеальный, было бы здорово, если б кто-то подсказал более изящний способ.

20.04.2010 · 13-ый · 2 комментария
Метки: , , , , ,  · Рубрики: 13-ый, MS SQL

2 комментария

  1. Hunter - 20.04.2010

    А если к имени временной таблицы добавлять суффикс, зависящий от уровня вложенности?

  2. 13-ый - 20.04.2010

    не понял зачем его добавлять и о какой вложенности идет речь…

    если о запрете по вложенность инсерта из хп, то тут системная хп, которая делает инсерт совсем из других таблиц и совсем других данных.

Написать комментарий