SSMS y resultados del servidor registrado

8

Antecedentes :

Estamos tratando de crear un arnés de prueba "primario" para uno de nuestros equipos de soporte. Sin saber qué servidores en un momento dado serán los principales, se les ha indicado que ejecuten el TSQL contra un grupo de servidores registrados. El grupo de servidores registrados consta de todos los servidores de la AG. El objetivo es ejecutar solo TSQL en el servidor primario actual:

Arnés de prueba actual :

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

Problema :

Si el primer servidor que responde a la consulta del servidor múltiple no devuelve ningún resultado, SSMS asumirá que el conjunto de resultados correcto no es un conjunto de resultados, incluso si otros servidores luego regresan con un conjunto de resultados. Entonces, en este escenario, no se devuelven resultados ... esto no es correcto y no es la funcionalidad esperada.

¿Alguien puede pensar en una forma, con SSMS (esta es la herramienta más familiar para el equipo de CS), para forzar la ejecución solo en el servidor primario actual?

Harry
fuente
¿Ha considerado hacer que se conecten al oyente AG, y así ejecutar la consulta de esa manera? Asegurará siempre golpear el primario.
Nic
Desafortunadamente, esto no es posible. Tenemos un montón de inquilinos con oyentes nombrados de forma idéntica. Simplemente no funcionará en este caso.
Harry

Respuestas:

10

Me he encontrado con esto ** antes, y si recuerdo correctamente, para garantizar que siempre obtenga resultados con consultas de varios servidores, debe forzar un conjunto de resultados vacío cuando de lo contrario no se devolverían filas. Es decir, necesita una ELSErama sobre eso IFy dentro de ELSEesto haría algo como lo siguiente:

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

Esto produce un conjunto de resultados vacío que tiene los nombres y tipos de datos adecuados.

O bien, y no lo he intentado en el pasado (solo pensé que estaba escribiendo esto), pero es posible que pueda salirse con la pausa simplemente en esa ELSErama de modo que el servidor primario / previsto siempre pueda devolver su conjunto de resultados primero (que es el problema real aquí: el primer servidor que responde define la estructura a la que deben adherirse todas las demás respuestas). Por lo tanto, lo siguiente podría funcionar como lo único en ELSE:

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

Pero no recuerdo si hacer que otros servidores no devuelvan ningún resultado provocó que se mostrara un mensaje de error en la pestaña "Mensajes". Si eso sucede, entonces el conjunto de resultados vacío es definitivamente el camino a seguir. Pero si esto funciona, entonces podría funcionar mejor en una plantilla general (como parece ser su caso) ya que no requeriría ajustar el conjunto de resultados forzado y vacío cada vez que se usa.

ACTUALIZAR:

El OP verificó que:

  • de WAITFOR DELAYhecho funcionó, y
  • las réplicas informaron el mensaje de error, pero no presentaron un problema para el uso del OP

** La situación con la que me encontré fue similar, pero no tenía nada que ver con los Grupos de disponibilidad o con los resultados deseados de un solo servidor. Nuestra situación era que teníamos 18 servidores con el mismo esquema de datos diferentes y necesitábamos hacer varias tareas de mantenimiento, agregaciones en los 18 nodos. Hubo algunos procedimientos almacenados que, por el motivo que sea, ocasionalmente no devolvieron ningún conjunto de resultados, y cualquiera que sea el motivo, no se pudo solucionar dentro del procedimiento almacenado. Entonces, dependiendo de qué nodo regresó primero, la mayoría de las veces todo estuvo bien, pero de vez en cuando el nodo que a veces no devolvió ningún conjunto de resultados regresó primero. Entonces, tuve que hacer algo como volcar los resultados en una tabla temporal y si @@ROWCOUNTeso INSERT...EXECfuera 0, entonces seleccionaría el conjunto de resultados forzado y vacío.

Solomon Rutzky
fuente
2
¡Nunca hubiera pensado en eso! ¡La espera del retraso funciona como un campeón! Definitivamente ahorra de construir el resultado vacío establecido. You do man @srutzky Gracias
Harry
@Harry De nada, y gracias :-). Acabo de actualizar mi respuesta para ser un poco más claro sobre el beneficio del WAITFOR DELAYenfoque y que usted confirmó que funcionó, ¡así que gracias por eso!
Solomon Rutzky
1
Es lo mejor que he visto esta semana.
Brent Ozar
Definitivamente arroja un error en las réplicas, sin embargo, en este caso, esto está completamente bien.
Harry
@Harry Gracias de nuevo por darnos tu opinión. Lo he agregado a mi respuesta, junto con una explicación al final de la situación que encontré.
Solomon Rutzky
0

Siempre he usado una tabla temporal para devolver resultados para obtener respuestas consistentes de todos los servidores de un grupo. Las consultas de varios servidores son una de mis cosas favoritas sobre SSMS.

Tony
fuente