No soy un experto en replicación, pero azar del destino, últimamente me ha tocado investigar e intentar resolver algunos problemas con esta función de SQL Server. En una de estas ocasiones, me di cuenta de que uno de los errores era bastante común, pero no había gran cantidad de información en internet sobre ello (al menos en inglés), por lo que aquí os traigo cómo investigarlo y solucionarlo.
Error «Violation of PRIMARY KEY constraint» en Replicación
El problema empieza al recibir una alerta en nuestro monitor indicando que las publicaciones de nuestro cliente no están funcionando correctamente. Al conectarme a la instancia y abrir el monitor de la replicación configurada, pude ver el siguiente error generándose a la hora de pasar los datos del distribuidor al suscriptor.
El error que podíamos ver era el siguiente:
Violation of PRIMARY KEY constraint ‘PK__Jobs__0DAF0CB0’. Cannot insert duplicate key in object ‘dbo.Jobs’. The duplicate key value is (47ee8dc2-6b00-4df1-a229-a3e64bbbf031). (Source: MSSQLServer, Error number: 2627)
Básicamente, se está intentando insertar una fila en la base de datos de destino con una clave primaria que ya existe.
Investigación y solución
Lo primero que habrá que hacer es identificar qué es lo que se está ejecutando y qué sentencia de esta replicación está generando este error. Para esto, ejecutaremos el siguiente script:
/* Copiar el numero de secuencia que vemos en el monitor de replicación */ -- 0x00325D3900055A58001500000000 SELECT art.publisher_id , art.publisher_db , art.publication_id , art.article , art.article_id , art.destination_object , art.source_owner , art.source_object FROM distribution.dbo.MSarticles AS art JOIN distribution.dbo.MSrepl_commands AS com ON art.Article_id = com.Article_id WHERE com.xact_seqno = 0x00325D3900055A58001500000000
Esto nos arrojará la información que está intentando enviar y replicar en la secuencia que se muestra en el error. A partir de esta información, ya podremos obtener el resto.
Usando la información del script anterior, ejecutamos el siguiente script.
EXEC distribution.dbo.sp_browsereplcmds @xact_seqno_start = '0x00325D3900055A58001500000000' , @xact_seqno_end = '0x00325D3900055A58001500000000' , @publisher_database_id = 1 , @article_id = 85 , @command_id = 32
El resultado será algo similar a esto:
Si scrolleamos hacia la derecha en el resultado de esta query (lo siento no lo capturé porque soy bobo) , encontramos las sentencias que se están ejecutando y, por lo tanto, la información sobre el insert que se está intentando ejecutar en la base de datos.
A partir de aquí, solo tenéis que comprobar esta información y decidir si queréis eliminar esta sentencia de insert o si queréis eliminar la fila ya existente en la base de datos para que pueda insertarse la nueva.
Espero que esta información haya sido útil.