¿Cómo puedo monitorear una base de datos de SQL Server en busca de cambios en una tabla sin usar activadores o modificar la estructura de la base de datos de alguna manera? Mi entorno de programación preferido es .NET y C #.
Me gustaría poder admitir cualquier SQL Server 2000 SP4 o posterior. Mi aplicación es una visualización de datos atornillada para el producto de otra compañía. Nuestra base de clientes es de miles, por lo que no quiero tener que exigir que modifiquemos la tabla de proveedores externos en cada instalación.
Por "cambios en una tabla" quiero decir cambios en los datos de la tabla, no cambios en la estructura de la tabla.
En última instancia, me gustaría que el cambio desencadenara un evento en mi aplicación, en lugar de tener que verificar los cambios a intervalos.
Parece que el mejor curso de acción dados mis requisitos (sin desencadenantes o modificación del esquema, SQL Server 2000 y 2005) es utilizar la BINARY_CHECKSUM
función en T-SQL . La forma en que planeo implementar es esta:
Cada X segundos ejecute la siguiente consulta:
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);
Y compare eso con el valor almacenado. Si el valor ha cambiado, revise la tabla fila por fila usando la consulta:
SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);
Y compare las sumas de verificación devueltas con los valores almacenados.
fuente
Respuestas:
Echa un vistazo al comando CHECKSUM:
Eso devolverá el mismo número cada vez que se ejecute siempre que el contenido de la tabla no haya cambiado. Vea mi publicación sobre esto para más información:
CHECKSUM
Así es como lo usé para reconstruir las dependencias de caché cuando las tablas cambiaron:
dependencia de la caché de la base de datos ASP.NET 1.1 (sin desencadenantes)
fuente
Lamentablemente, CHECKSUM no siempre funciona correctamente para detectar cambios .
Es solo una suma de control primitiva y ningún cálculo de verificación de redundancia cíclica (CRC).
Por lo tanto, no puede usarlo para detectar todos los cambios, por ejemplo, los cambios simétricos dan como resultado el mismo CHECKSUM.
P.ej. la solución
CHECKSUM_AGG(BINARY_CHECKSUM(*))
siempre entregará 0 para las 3 tablas con contenido diferente:fuente
¿Por qué no quieres usar disparadores? Son buenos si los usa correctamente. Si los usa como una forma de hacer cumplir la integridad referencial, es cuando pasan de bueno a malo. Pero si los usa para monitorear, en realidad no se consideran tabú.
fuente
¿Con qué frecuencia necesita verificar los cambios y qué tan grandes (en términos de tamaño de fila) son las tablas en la base de datos? Si usa el
CHECKSUM_AGG(BINARY_CHECKSUM(*))
método sugerido por John, escaneará cada fila de la tabla especificada. LaNOLOCK
sugerencia ayuda, pero en una base de datos grande, todavía está presionando cada fila. También necesitará almacenar la suma de verificación para cada fila para que sepa que una ha cambiado.¿Has considerado ir a esto desde un ángulo diferente? Si no desea modificar el esquema para agregar desencadenantes (lo cual tiene sentido, no es su base de datos), ¿ha considerado trabajar con el proveedor de la aplicación que hace la base de datos?
Podrían implementar una API que proporcione un mecanismo para notificar a las aplicaciones accesorias que los datos han cambiado. Podría ser tan simple como escribir en una tabla de notificación que enumera qué tabla y qué fila se modificaron. Eso podría implementarse a través de disparadores o código de aplicación. Por su parte, usted no importaría, su única preocupación sería escanear la tabla de notificaciones periódicamente. El rendimiento alcanzado en la base de datos sería mucho menor que escanear cada fila en busca de cambios.
La parte difícil sería convencer al proveedor de la aplicación para implementar esta función. Dado que esto se puede manejar completamente a través de SQL a través de disparadores, puede hacer la mayor parte del trabajo por ellos escribiendo y probando los disparadores y luego llevando el código al proveedor de la aplicación. Al hacer que el proveedor admita los desencadenantes, evita la situación en la que agregar un desencadenador reemplaza inadvertidamente un desencadenante suministrado por el proveedor.
fuente
Desafortunadamente, no creo que haya una manera limpia de hacer esto en SQL2000. Si limita sus requisitos a SQL Server 2005 (y posterior), entonces está en el negocio. Puedes usar la
SQLDependency
clase enSystem.Data.SqlClient
. Consulte Notificaciones de consulta en SQL Server (ADO.NET) .fuente
Tener un trabajo DTS (o un trabajo iniciado por un servicio de Windows) que se ejecuta en un intervalo determinado. Cada vez que se ejecuta, obtiene información sobre la tabla dada usando las tablas INFORMATION_SCHEMA del sistema y registra estos datos en el repositorio de datos. Compare los datos devueltos con respecto a la estructura de la tabla con los datos devueltos la vez anterior. Si es diferente, entonces sabes que la estructura ha cambiado.
Ejemplo de consulta para devolver información sobre todas las columnas de la tabla ABC (idealmente enumerando solo las columnas de la tabla INFORMATION_SCHEMA que desea, en lugar de usar * select ** como lo hago aquí):
Monitorearía diferentes columnas y vistas de INFORMATION_SCHEMA dependiendo de cómo defina exactamente los "cambios en una tabla".
fuente
Adivina aquí: si no quieres modificar las tablas de terceros, ¿puedes crear una vista y luego activarla?
fuente
Verifique la última fecha de confirmación. Cada base de datos tiene un historial de cuándo se realiza cada confirmación. Creo que es un estándar de cumplimiento de ACID.
fuente