Estoy buscando las mejores prácticas para tratar los trabajos programados del Agente SQL Server en los grupos de disponibilidad de SQL Server 2012. Tal vez me perdí algo, sin embargo, en el estado actual, siento que el Agente SQL Server no está realmente integrado con esta gran característica de SQL2012.
¿Cómo puedo hacer que un trabajo de agente SQL programado sea consciente de un cambio de nodo? Por ejemplo, tengo un trabajo ejecutándose en el nodo primario que carga datos cada hora. Ahora, si el primario se cae, ¿cómo puedo activar el trabajo en el secundario que ahora se convierte en primario?
Si programo el trabajo siempre en el secundario, falla porque entonces el secundario es de solo lectura.
Respuestas:
Dentro de su trabajo del Agente SQL Server, tenga alguna lógica condicional para comprobar si la instancia actual cumple el rol particular que está buscando en su grupo de disponibilidad:
Todo lo que hace es extraer el rol actual de la réplica local, y si está en el
PRIMARY
rol, puede hacer lo que sea que su trabajo deba hacer si es la réplica principal. ElELSE
bloque es opcional, pero es para manejar la lógica posible si su réplica local no es primaria.Por supuesto, cambie
'YourAvailabilityGroupName'
la consulta anterior a su nombre de grupo de disponibilidad real.No confunda grupos de disponibilidad con instancias de clúster de conmutación por error. Si la instancia es la réplica primaria o secundaria para un grupo de disponibilidad determinado no afecta a los objetos a nivel de servidor, como los trabajos del Agente SQL Server, etc.
fuente
En lugar de hacer esto por trabajo (verificando cada trabajo por el estado del servidor antes de decidir continuar), he creado un trabajo ejecutándose en ambos servidores para verificar en qué estado se encuentra el servidor.
Este enfoque proporciona una serie de cosas
el script verifica la base de datos en el campo a continuación
Este proceso se ejecuta cada 15 minutos en cada servidor. (tiene la ventaja adicional de agregar un comentario para informar a las personas por qué se deshabilitó el trabajo)
No es infalible, pero para cargas nocturnas y trabajos por hora, hace el trabajo.
Incluso mejor que tener este procedimiento ejecutado en un horario, en lugar de eso, ejecútelo en respuesta a Alert 1480 (alerta de cambio de rol de AG).
fuente
Soy consciente de dos conceptos para lograr esto.
Requisito previo: Basado en la respuesta de Thomas Stringer, creé dos funciones en la base de datos maestra de nuestros dos servidores:
Hacer que un trabajo finalice si no se ejecuta en la réplica principal
Para este caso, cada trabajo en ambos servidores necesita cualquiera de los siguientes dos fragmentos de código como el Paso 1:
Verificar por nombre de grupo:
Verificar por nombre de base de datos:
Sin embargo, si usa este segundo, tenga cuidado con las bases de datos del sistema; por definición, no pueden ser parte de ningún grupo de disponibilidad, por lo que siempre fallará para ellos.
Ambos funcionan de forma inmediata para los usuarios administradores. Para los usuarios que no son administradores, debe agregar permisos adicionales, uno de ellos sugerido aquí :
Si configura la acción de falla para Salir del informe de trabajo exitoso en este primer paso, no obtendrá el registro de trabajo lleno de feos signos de cruz roja, para el trabajo principal se convertirán en señales de advertencia amarillas.
Desde nuestra experiencia, esto no es ideal. Al principio adoptamos este enfoque, pero rápidamente perdimos la noción de encontrar trabajos que realmente tuvieran un problema, porque todos los trabajos de réplica secundaria saturaban el registro de trabajos con mensajes de advertencia.
Lo que luego buscamos es:
Trabajos proxy
Si adopta este concepto, en realidad necesitará crear dos trabajos por tarea que desee realizar. El primero es el "trabajo proxy" que comprueba si se está ejecutando en la réplica principal. Si es así, comienza el "trabajo de trabajo", de lo contrario, finaliza con gracia sin saturar el registro con mensajes de advertencia o error.
Si bien personalmente no me gusta la idea de tener dos trabajos por tarea en cada servidor, creo que es definitivamente más fácil de mantener, y no tiene que establecer la acción de falla del paso para Salir del informe de éxito , lo cual es un poco torpe.
Para los trabajos, adoptamos un esquema de nombres. El trabajo proxy solo se llama
{put jobname here}
. El trabajo del trabajador se llama{put jobname here} worker
. Esto hace posible automatizar el inicio del trabajo del trabajador desde el proxy. Para hacerlo, agregué el siguiente procedimiento a ambos dbs maestros:Esto utiliza la
svf_AgReplicaState
función que se muestra arriba, puede cambiarla fácilmente para verificar usando el nombre de la base de datos llamando a la otra función.Desde el único paso del trabajo proxy, lo llamas así:
Esto utiliza tokens como se muestra aquí y aquí para obtener la identificación del trabajo actual. El procedimiento luego obtiene el nombre del trabajo actual de msdb, lo agrega
worker
y comienza a usar el trabajo del trabajadorsp_start_job
.Si bien esto aún no es ideal, mantiene los registros de trabajo más ordenados y fáciles de mantener que la opción anterior. Además, siempre puede ejecutar el trabajo proxy con un usuario sysadmin, por lo que no es necesario agregar permisos adicionales.
fuente
Si el proceso de carga de datos es una simple consulta o llamada de procedimiento, puede crear el trabajo en ambos nodos y dejar que determine si es el nodo primario en función de la propiedad Updateability de la base de datos, antes de que ejecute el proceso de carga de datos:
fuente
Siempre es mejor crear un nuevo Paso de trabajo que verifique si es una Réplica primaria, entonces todo está bien para continuar con la ejecución del trabajo, de lo contrario, si es una Réplica secundaria, luego detenga el trabajo. No falle el trabajo, de lo contrario seguirá enviando notificaciones innecesarias. En su lugar, detenga el trabajo para que se cancele y no se envíen notificaciones cada vez que estos trabajos se ejecuten en la réplica secundaria.
A continuación se muestra el script para agregar un primer paso para un trabajo específico.
Nota para ejecutar el script:
Si hay varios grupos de disponibilidad, establezca el nombre de AG en la variable @AGNameToCheck_IfMoreThanSingleAG en cuanto a qué AG se debe verificar su estado de réplica.
También tenga en cuenta que este script debería funcionar bien incluso en aquellos servidores que no tienen grupos de disponibilidad. Se ejecutará solo para las versiones de SQL Server 2012 y posteriores.
fuente
Otra forma es insertar un paso en cada trabajo, que debe ejecutarse primero, con el siguiente código:
Establezca este paso para continuar con el siguiente paso en caso de éxito y para salir del trabajo informando éxito en caso de error.
Me parece más limpio agregar un paso adicional en lugar de agregar lógica adicional a un paso existente.
fuente
Otra opción más nueva es usar master.sys.fn_hadr_is_primary_replica ('DbName'). He encontrado esto súper útil cuando uso el Agente SQL para realizar el mantenimiento de la base de datos (junto con un cursor que he usado durante años) y también cuando ejecuto una ETL u otra tarea específica de la base de datos. El beneficio es que destaca la base de datos en lugar de mirar todo el Grupo de disponibilidad ... si eso es lo que necesita. También hace que sea mucho más improbable que un comando se ejecute contra una base de datos que "estaba" en el primario, pero digamos que ocurrió una conmutación por error automática durante la ejecución del trabajo, y ahora está en una réplica secundaria. Los métodos anteriores que miran la réplica principal echan un vistazo y no se actualizan. Tenga en cuenta que esta es solo una forma diferente de lograr resultados muy similares y brindar un control más granular, si lo necesita. Además, la razón por la que este método no se discutió cuando se hizo esta pregunta es porque Microsoft no lanzó esta función hasta después de que se lanzó SQL 2014. A continuación hay algunos ejemplos de cómo se puede usar esta función:
Si desea usar esto para el mantenimiento de la base de datos de usuarios, esto es lo que uso:
¡Espero que este sea un consejo útil!
fuente
Yo uso esto:
fuente