Blog Archive

SQL-Server

 
Rubén Garrigós

SQL Server Transactional Replication: Troubleshooting nivel 200

2011-08-10 01:00:00 por Rubén Garrigós

Uno de los inconvenientes cuando añadimos replicación a nuestro entorno es que añade labores extras de monitorización y además los errores en el proceso de réplica pueden llegar a ser complejos de diagnosticar. En el anterior post vimos cómo podemos utilizar el monitor de replicación para monitorizar el estado de nuestra réplica. Si sospechamos que tenemos algún tipo de problema en nuestra replicación, éste debería ser el primer sitio donde deberíamos acudir para verificar el estado actual de nuestra réplica.

Cada réplica requiere un proceso de verificación ligeramente distinto y que deberemos adaptar a nuestras necesidades concretas. Si seguimos con el ejemplo del post anterior tenemos una replicación transaccional unidireccional en marcha. El proceso de verificación a seguir podría ser el siguiente:

1. Abrir el monitor de replicación y comprobar que el agente del log de transacciones está en marcha y no muestra ningún error

SQL Server Transaction Replication: Estado del agente del log de transacciones

2. Comprobar desde el monitor de replicación que todos nuestros agentes de distribución asociados a los subscriptores están funcionando y no muestran ningún error:

SQL Server Transaction Replication: Estado del agente de distribución

3. Introducir un Token de traza desde el monitor de replicación y comprobar que la latencia es coherente con lo esperado. Si hemos configurado la réplica transaccional con los valores por defecto la latencia total debería estar por debajo de 10 segundos:

SQL Server Transaction Replication: Tracer Tokens

Si al analizar las latencias vemos que por ejemplo del publicador al distribuidor tardamos 3 segundos y del distribuidor al subscriptor tardamos 60 segundos ya tenemos una pista de por donde tenemos que orientar la resolución de nuestro problema.

En general en una replicación transaccional unidireccional se presupone que los datos en destino serán de solo lectura o, si hay escrituras, éstas no producirán colisiones con los datos replicados. Por ejemplo si recordamos el anterior post sobre replicación transaccional, una de las opciones que se ofrece durante la configuración de la publicación era la configuración de filtros. Con un filtro activo sería viable mantener inserciones de datos en la misma tabla que la réplica está funcionando siempre que no colisionemos con el filtro. A continuación vamos a simular una situación que causaría un error en la réplica y veremos de que forma podemos diagnosticar la causa exacta y resolver el problema.

Para ello comprobaremos que tenemos los agentes en marcha correctamente antes de comenzar mediante el monitor de réplica y además lanzaremos una consulta que nos devuelva el último contacto insertado en el publicador:

SQL Server Transaction Replication: Buscamos una colisión

Haremos lo mismo en el subscriptor:

SQL Server Transaction Replication: Buscamos una colisión insert-insert

A continuación procederemos a realizar una inserción “no adecuada” en el subscriptor, utilizando para ello un ContactID que colisionará al irse incrementando el contador. Por ejemplo el ContactID 19981 acabará colisionando tras realizar unas pocas inserciones. Tras realizar esta inserción en el subscriptor procederemos a realizar varias inserciones en el publicador hasta alcanzar el 19981 al menos:

SQL Server Transaction Replication: Realizamos inserciones en el subscriptor y en el publicador

Si una vez estamos en este estado realizamos una inserción de un nuevo registro en el publicador, la inserción se realizará con éxito, independientemente de los problemas que ello pueda causar al subscriptor posteriormente. Si accedemos al monitor de replicación veremos como el subscriptor está teniendo algunos problemas aplicando comandos y estamos teniendo errores:

SQL Server Transaction Replication: Vemos en el monitor que tenemos un error

SQL Server Transaction Replication: Reintentos automáticos de entrega de comandos

Pasados unos segundos los reintentos se convertirán en un error más concreto:

SQL Server Transaction Replication: Error indicando la constraint problemática

Como vemos, no se nos indica cual es el registro afectado concretamente únicamente la restricción problemática (la clave primaria) y la tabla afectada. En estas situaciones lo que recomendamos es detener el agente afectado, lanzar una traza de SQL Server Profiler y obtener más datos directamente de la actividad en la base de datos del subscriptor. Lanzaremos una traza filtrando únicamente aquella actividad proveniente del agente de réplica lo cual en nuestro caso podemos conseguirlo filtrando por like ‘%_publi’:

SQL Server Transaction Replication: Filtramos en SQL profiler para capturar la actividad del agente

Una vez tenemos la traza en marcha los propios reintentos del agente nos mostrarán aquella fila que está dándole problemas con la inserción por colisión de clave primaria:

SQL Server Transaction Replication: Error en SQL profiler

En el texto del comando que está fallando podemos deducir que el fallo se produce en una inserción (procedimiento almacenado con prefijo sp_MSins), que corresponde a la tabla Person.Contact (sufijo PersonContact en el procedimiento):

exec [dbo].[sp_MSins_PersonContact] 19981,0,NULL,N'Crystal',NULL,N'Hu',NULL,N'crystal21@adventure-works.com',0,N'1 (11) 500 555-0126',N'ZEgQH9qZIPiLgyBHYw/dD1FJQNpdQyIAa+BFfKX5/jg=',N'7iy/umc=',NULL,N'{2495BFFD-2041-4C4F-9238-8BC1E204C400}','2003-11-17 00:00:00'

Si examinamos el cuerpo del procedimiento veremos que el primer parámetro corresponde efectivamente con el ContactID por lo que ya sabemos que la solución para poder reanudar la réplica pasa por eliminar dicho registro del subscriptor. Una vez eliminado del subscriptor veremos que la réplica es capaz de recuperarse sin problemas:

SQL Server Transaction Replication: Una vez borrado el registro, todo se recupera y vuelve a la normalidad

Como conclusión debemos tener en cuenta que cuanto tengamos un problema con nuestra replicación el primer paso es acudir al monitor de replicación para intentar obtener pistas de dónde puede estar el problema. Es posible que un agente se encuentre simplemente detenido por un error de un operador que lo deshabilitó por error. Es posible también que problemas de red impidan al agente de distribución conectar con el subscriptor o que el subscriptor esté saturado de forma que las latencias sean mucho mayores de las habituales. Afortunadamente la mayoría de errores son diagnosticables mediante los errores que aparecen en el monitor y cuando no siempre tendremos nuestro fiel SQL Profiler listo para poder ayudarnos.

Comments

#re: sql server transactional replication: troubleshooting nivel 200
Tuesday, May 15, 2012 - 05:23 PM by Andris Marte
Hola Rubén, ahora te escribo para que me ayude a cambiar una de las propiedades de la Replicación Transaccional que tengo en producción lista, aunque tambien tengo un escenario tecnicamente hablando igual. El detalle es que el ambiente que tengo en producción yo manejo una herramienta nativa de la aplicación el cuál es para almacenar los registros que cumplan con ciertos criterios y condiciones, y ya es tiempo de almacenar y/o archivar dichos registros. En este caso cuando archivamos y/o almacenamos esos registros en otra base de datos automaticamente se eliminan de la base de datos de producción el cual es la base de datos que tengo replicada. Ahora bien necesito almacenar pero sin enviar el comando de DELETE a la base de datos replicada a mi otro suscriptor porque del otro lado se necesitan todos los registros para mantenerlo como data historica, ya yo realicé los pasos para no replicar dicho comando, pero realmente como quiera lo está haciendo, me esta replicando el comando al suscriptor y consecuentemente me está eliminado los registros tambien. por favor ayudame quizas desabilitando los stores procedure en el suscriptor pienso yo. Recuerda Rubén que mi ambiente lo inicié con un backup "initialize with backup" y no me permite hacer un Snapshots y reinicializar la base de datos nuevamente... Eso pienso Yo!! bueno gracias nuevamente y esperando de tus comentarios. -- Respuesta El cambio que indicas implica la reinicialización de snaphot y la consecuente aplicación de este. Ya que esto no es válido en tu escenario podrías proceder a dejar el procedimiento sp_MSdel_XXX correspondiente del subscriptor con el cuerpo vacío. Un problema que tendrás es que deberías hacer este cambio, lanzar la historificación y luego volverlo a dejar como estaba una vez se repliquen los "borrados falsos" para que los borrados que sean parte del funcionamiento normal de la aplicación sigan funcionando posteriormente. Por otra parte al hacer esto que comentas acabarás teniendo las tablas desincronizadas y podrás encontrarte con problemas por lo que no te lo recomendaría como solución a largo plazo. Quizás sería mejor que el subscriptor tuviera también una base de datos histórica y que replicaras la base de datos histórica hacia el subscriptor también. De esta forma se realizarían borrados en una base de datos e inserciones en la otra por lo que siempre tendrías disponible el dato en el subscriptor.
#re: sql server transactional replication: troubleshooting nivel 200
Wednesday, May 16, 2012 - 05:06 PM by Andris Marte
Hey Hola Rubén nuevamente, Fijate estuve haciendo pruebas dejando vacio los procedimientos almacenados en el suscriptor los que hacen referencia a los nombres de los articulos (en este casos solo son tablas) por ejemplo: spMSdel_TableName1.......spMSdel_TableNameX verdad? bueno lo deje vacio y realmente como quiera hace el llamado y elimina los registros del lado de mi suscriptor. sería correcto lo que estoy haciendo? -- Respuesta Si estás utilizando borrados mediante dicho procedimiento almacenado el dejarlo vacío funcionaría correctamente. Otra cosa es que estés haciendo los borrados de otra forma, que hubieses cambiado la configuración del artículo o los estés borrando por otro lado, o se borren indirectamente con un trigger, etc. En fin, que si no es el procedimiento (al que le has dejado el cuerpo vacío) de algún otro sitio tienen que venir los borrados que no tenga que ver con la réplica. Las filas no se van a borrar por arte de magia, tendrás que investigarlo tu mismo con Profiler por ejemplo. De todas formas sigo insistiendo en que no me parece buena idea la configuración que pretendes mantener donde las tablas no se encuentren sincronizadas y ciertos registros estén en el subscriptor pero no en el publicador.
#re: sql server transactional replication: troubleshooting nivel 200
Wednesday, May 16, 2012 - 10:50 PM by Andris Marte
Rubén es cierto todo lo que me dices, ni yo mismo se porque estoy interesado en forzar de esta manera si realmente no voy a tener las tablas sincronizadas hace unas semanas estaba sumamente preocupado por no tener mis tablas sincronizadas. realmente me decido a no forzar la jugada como dicemos aqui en Republica Dominicana. Ah dame tu usuario de Twitter si tienes para seguirte, claro si publicas posts relacionados a SQLServer...Gracias Rubén!!
Leave a Comment
(*) Title:
(*) Name:
Your URL:
(*) Comments:
Follow us on: