SSMS и результаты зарегистрированного сервера

8

Фон :

Мы пытаемся создать AG "основной" тестовый комплект для одной из наших групп поддержки. Не зная, какие серверы в любой момент времени будут первичными, им было поручено выполнить TSQL для зарегистрированной группы серверов. Зарегистрированная группа серверов состоит из всех серверов в AG. Цель состоит в том, чтобы выполнить TSQL только на текущем основном сервере:

Текущий тестовый жгут :

IF EXISTS (SELECT *
FROM sys.dm_hadr_availability_replica_states AS HARS 
INNER JOIN sys.dm_hadr_availability_replica_cluster_states AS HACS ON HACS.replica_id = HARS.replica_id 
    WHERE (HARS.role_desc = 'PRIMARY') AND (HACS.replica_server_name LIKE @@SERVERNAME))
BEGIN
<<SOME CODE TO EXECUTE>>
END

Проблема :

Если первый сервер, который отвечает обратно на многосерверный запрос, не возвращает никаких результатов, SSMS будет считать, что правильный набор результатов не является набором результатов, даже если другие серверы позже возвращаются с набором результатов. Таким образом, в этом случае результаты не возвращаются ... это неверно и не является ожидаемой функциональностью.

Может кто-нибудь придумать, как с помощью SSMS (это наиболее знакомый инструмент для команды CS) принудительно выполнять только на текущем основном сервере?

Гарри
источник
Рассматривали ли вы возможность их подключения к прослушивателю AG, таким образом выполняя запрос таким образом? Это обеспечит всегда попадание в основной предмет.
Nic
К сожалению, это невозможно. У нас есть масса арендаторов с одинаковыми именами слушателей. Просто не сработает в этом случае.
Гарри

Ответы:

10

Я сталкивался с этим ** раньше, и, если я правильно помню, чтобы всегда получать результаты с многосерверными запросами, вам нужно принудительно установить пустой набор результатов, если в противном случае строки не были бы возвращены. Это значит, что вам нужна ELSEветка, IFи внутри ELSEвы бы сделали что-то вроде следующего:

SELECT CONVERT(DATETIME, NULL) AS [Col1name],
       CONVERT(DECIMAL(12, 5), NULL) AS [Col2name],
       ...{additional fields}...
WHERE  1 = 0;

Это приводит к пустому набору результатов с правильными именами и типами данных.

ИЛИ, и я не пробовал это в прошлом (просто подумал об этом, когда я набирал это), но вы могли бы сойти с рук с простой паузой в этой ELSEветви, так что основной / предполагаемый сервер всегда может вернуть свой сначала набор результатов (что является настоящей проблемой: первый отвечающий сервер определяет структуру, которой должны придерживаться все остальные ответы). Следовательно, следующее может работать как единственное в ELSE:

WAITFOR DELAY '00:00:10'; -- 10 seconds (just needs to be longer than the real query takes)

Но я не помню, чтобы другие серверы вообще ничего не возвращали, что вызвало сообщение об ошибке на вкладке «Сообщения». Если это произойдет, то пустой набор результатов определенно поможет. Но если это сработает, то это может работать лучше в общем шаблоне (как кажется в вашем случае), так как для этого не потребуется корректировать принудительный пустой набор результатов при каждом его использовании.

ОБНОВИТЬ:

ФП проверил, что:

  • WAITFOR DELAYдействительно работает, и
  • реплики действительно сообщали об ошибке, но это не представляло проблемы для использования OP

** Ситуация, с которой я столкнулся, была похожей, но не имела ничего общего ни с группами доступности, ни с желанием получить результаты только с одного сервера. Наша ситуация состояла в том, что у нас было 18 серверов одной и той же схемы с разными данными, и нам нужно было выполнять различные задачи по обслуживанию, объединяя все 18 узлов. Существовали некоторые хранимые процедуры, которые по какой-то причине иногда не возвращали какой-либо набор результатов, и какова бы ни была эта причина, она не могла быть исправлена ​​в хранимой процедуре. Таким образом, в зависимости от того, какой узел возвратился первым, большую часть времени все было в порядке, но время от времени узел, который иногда не возвращал набор результатов, возвращал первым. Итак, мне нужно было сделать что-то вроде вывода результатов во временную таблицу, и если бы @@ROWCOUNTэто INSERT...EXECбыло 0, я бы выбрал принудительный пустой набор результатов.

Соломон Руцкий
источник
2
Никогда бы не подумал об этом !! Ожидание задержки работает как чемпион! Определенно избавляет от создания пустого результата, изложенного. Ты делаешь человека @srutzky Спасибо
Гарри
@ Гарри, пожалуйста, и спасибо :-). Я только что обновил свой ответ, чтобы немного прояснить преимущества этого WAITFOR DELAYподхода, и вы подтвердили, что он сработал, поэтому спасибо за это!
Соломон Руцкий
1
Это самая крутая вещь, которую я видел на этой неделе.
Брент Озар
Это определенно вызывает ошибку на репликах, однако в этом случае это вполне нормально.
Гарри
@ Гарри Спасибо еще раз за предоставленную обратную связь. Я добавил его в свой ответ вместе с объяснением в нижней части ситуации, с которой я столкнулся.
Соломон Руцкий
0

Я всегда использовал временную таблицу для получения результатов, чтобы получить согласованные ответы от всех серверов в группе. Многосерверные запросы - одна из моих любимых вещей в SSMS.

Тони
источник