Capturar fecha y hora de cambio en SQL Server CDC

8

Así que comenzamos a explorar el uso de la captura de datos de cambios en una de nuestras bases de datos de producción. Nos gustaría saber la fecha y hora de cada cambio. Leyendo los tutoriales y tutoriales, etc., parece que el enfoque estándar es utilizar el LSN para relacionarse con la cdc.lsn_time_mappingtabla del sistema. Este enfoque funciona, pero no es muy directo ni eficaz cuando se habla de cientos de miles de cambios por día.

En un entorno de prueba, realicé el siguiente ajuste en las tablas de seguimiento de cambios. Emití una ALTER TABLEdeclaración para agregar una columna al final llamado [__ChangeDateTime]e hice su valor predeterminado GetDate(). El enfoque parece funcionar, el seguimiento de cambios todavía funciona normalmente, se están capturando las fechas y horas. Pero jugar con las tablas del sistema me pone un poco nervioso.

Si este no es un campo del sistema que Microsoft agregó desde el principio , deben haber tenido sus razones. Dado que en su lugar optaron por el LSN para el enfoque cdc.lsn_time_mapping, ¿me estoy preparando para los problemas creando mi propio truco de esta manera?

ACTUALIZAR:

Descubrimos durante las pruebas que GetDate () a veces no es lo suficientemente preciso para nuestras necesidades: múltiples cambios que se comparten al mismo tiempo. Se recomienda usar sysdatetime () y datetime2 para mover el valor al nanosegundo. Opción para 2008+ solo obviamente.

RThomas
fuente

Respuestas:

8

Recuerde que CDC utiliza un agente lector de registro para completar la tabla de cambios. ¿Por qué es eso importante? Mediante ese mecanismo, las filas se muestran en las tablas de cambios de forma asíncrona a los cambios realizados en las tablas base.

En realidad, se pueden registrar 3 puntos de tiempo diferentes, en orden cronológico inverso:

  1. La hora en que se entregó el cambio a la tabla de cambios (que es lo que está grabando).
  2. La hora a la que se comprometió la transacción que contenía el cambio (usando cdc.lsn_time_mapping)
  3. El tiempo con el que rellena manualmente una columna en la tabla base (utilizando una restricción predeterminada, un desencadenador, etc.).

Entonces, lo primero es tener claro lo que quieres grabar. Por lo general, nos importaría el # 2 o el # 3.

Si el mecanismo de mapeo LSN (# 2) no está funcionando lo suficientemente bien para usted, la única alternativa admitida es agregar una columna a la tabla base y completarla usted mismo (# 3).

Con respecto al cambio de las tablas internas, como cuestión de política, creo que es mejor evitar piratear con elementos internos cuando hay alternativas compatibles. Lo último que desea es un sistema de producción importante que no funcione, que necesite llamar al Soporte de productos y que se le niegue el servicio debido a algo como esto. No importa los problemas de que potencialmente rompa cosas (actualizaciones) o se rompa porque fue inesperado (apague CDC y vuelva a encenderlo, como se menciona en la otra respuesta).

Jon Seigel
fuente
3

Un ejemplo práctico:

USE Database;
GO

DECLARE @from_lsn binary(10), @to_lsn binary(10)
SET @from_lsn = sys.fn_cdc_get_min_lsn('schema_tablename')
SET @to_lsn = sys.fn_cdc_get_max_lsn()

SELECT
    sys.fn_cdc_map_lsn_to_time(__$start_lsn) AS 'Time'
    ,[Field1]
    ,[Field2]
    ,[Field3]
FROM [cdc].[fn_cdc_get_all_changes_schema_tablename]
  (@from_lsn, @to_lsn, N'all');
Gareth Orrill
fuente
Esta respuesta se beneficiaría de algunos comentarios que explican lo que está haciendo y por qué es relevante.
Erik
2

La única advertencia que daría es que esas tablas se eliminan automáticamente cuando CDC está deshabilitado. La columna no se volverá a crear automáticamente cuando la vuelva a alinear

Liam Confrey
fuente