2011-10-31 19 views
9

estoy ocupado creando un sistema en el que necesito para realizar un seguimiento de todos los cambios en el sistema. En otras palabras, cuando se cambia una columna en la base de datos, necesito saber qué tabla, qué columna, cuándo se realizó el cambio, por qué usuario, desde qué valor, a qué valor.cambios de registro para cada columna en una tabla

Mi primer pensamiento fue crear una segunda tabla para cada tabla con fines de registro, que contenga campos como column_name, updated_by, updated_on, from_value, to_value (manteniendo los campos from_value y to_value como cadenas para simplificar). Esto, sin embargo, esencialmente creará un duplicado de la base de datos.

Mi segunda opción sería crear una tabla masiva de un tipo similar (table_name, column_name, updated_by, updated_on, from_value, to_value) para todas las tablas, pero esto dará como resultado una tabla inmanejable, ya que los cambios estarán sucediendo frecuentemente.

Ambas opciones tienen el mismo problema, que no estoy seguro de cómo hacer referencia a las columnas de una tabla, y lo peor de todo, ¿cómo puedo manejar un cambio en los nombres de las columnas más adelante en la vida de la aplicación?

cualquier idea o sugerencia sería apreciada.

+1

Bueno, probablemente almacenara una ID de objeto de base de datos en lugar de una cadena con el nombre de la columna/tabla/etc, que podría resolver el problema de cambiar el nombre de las columnas (si la ID permanece igual, no estoy seguro si lo hace). De lo contrario, gran pregunta, siempre temía tener que hacer algo como esto yo mismo ... – GregL

Respuesta

3

Voy a hacer algunas suposiciones aquí:

  • usted no está limitado por el espacio en disco
  • usted tiene un modelo de datos no trivial
  • Tienes que ser capaz de reportar su información de auditoría/historial en un formato legible para humanos
  • no está trabajando con requisitos extremos de rendimiento o escalabilidad
  • la audiencia para sus datos de auditoría es nivel de usuario comercial, no nivel técnico.

En ese caso, la mejor solución que conozco es hacer de la "historia" un concepto de primera clase en su diseño. El link GregL citado tiene una buena descripción de esto; mi implementación más simple básicamente significa tener columnas "valid_from" y "valid_until" y "operator_id" en cada tabla, y usar "is_valid" en lugar de la operación de eliminación.

Esto es mejor que auditar los cambios en tablas separadas, porque le permite crear una imagen completa de sus datos en cualquier punto de la historia, completando todas las relaciones entre tablas, usando la misma lógica que su acceso a datos regular código. Eso, a su vez, significa que puede crear informes utilizando herramientas estándar de informes, respondiendo preguntas como "¿qué operador cambió los precios de todos los productos en la categoría de alimentos?", "¿Cuántos productos fueron menos de $ 100 el 1 de enero?" etc.

Consume más espacio y hace que su lógica de acceso a la base de datos sea más compleja. Tampoco funciona bien con las soluciones ORM.

+0

Esta ha sido una opción favorita, pero no se ajusta exactamente a mis necesidades. Por ejemplo, en un Producto, quiero tener una pestaña donde los usuarios puedan ver una tabla con todos los cambios realizados en ese Producto, cuándo y por quién. El ejemplo en el [enlace anterior] (http://www.simple-talk.com/sql/database-administration/database-design-a-point-in-time-architecture/) y [aquí] (http://www.indywebshop.com/bestpractices/2006/07/28/leaving-an-audit-trail-in-your-database/) implican que tendré que hacer una comparación fila por fila para listar una tabla de la historia de los cambios –

+0

De hecho, pero esto es (sobre todo) un problema para la interfaz de usuario.No es muy difícil escribir una función de biblioteca para diferenciar dos filas, columna por columna; depende, por supuesto, de su código front-end. En este modelo, mostraría un registro por cada cambio; puede hacer que cada columna que cambie entre filas sea verde. Eso es mucho más significativo (en mi opinión) que "el usuario x cambió el precio de y a z", porque los cambios tienden a venir en grupos, cambiando el precio y la descripción al mismo tiempo, por ejemplo. –

+0

Supongo que podría funcionar así. Iba a tener una serie de filas en la mesa (en el frente) con un montón de "usuario x precio cambiado de y a z", etc. etc. Además, la aplicación tendrá cerca de 100 tablas y yo Temo una segunda mesa para cada uno. Y algunas tablas tienen cerca de 50 columnas –

0

esto sería un poco raro, pero usted podría agregar una columna "InsertedOnTimestamp" para cada tabla como clave principal segundo. Entonces nunca permita que los usuarios actualicen las tablas y creen vistas que solo muestren el registro más reciente.

Select * From Table 
    Inner Join (Select ID, Max(InsertedOnTimestamp) as LastestRecord From Table Group By ID) as Latest 
    On Table.ID = LatestID AND Table.InsertedOnTimestamp = Latest.LatestRecord 

Sonidos messey como el infierno, sino una idea, no obstante ...

+0

No es una mala idea. El problema aparece, sin embargo, cuando tienes una tabla con 50 columnas y solo tienes un cambio en una de las columnas. Este método crearía innecesariamente una tabla masiva con datos duplicados. –

1

acabo de recordar que el término para este tipo de funcionalidad se denomina "auditoría". Una rápida búsqueda en Google de "diseñar la base de datos de auditoría completa" dio los siguientes enlaces interesantes - podría ser digno de una lectura:

http://www.simple-talk.com/sql/database-administration/database-design-a-point-in-time-architecture/

http://www.restfuldevelopment.net/david-kawliche/writing/time-after-time/

Best implementation for fully auditable data model?

http://www.sqlservercentral.com/articles/SQL+Puzzles/anaudittrailgenerator/2067/

Estaban los que me destacaron, es posible que encuentre mejores enlaces ahora que conoce la palabra clave de "auditoría".

+0

Gracias por los artículos. Miré a mi alrededor y encontré algunas más, pero está en la misma línea que las respuestas ya provistas –

1

Compruebe mi answer for the question "history rows management in database" Describe la solución que utilicé con los pros y contras de ese enfoque.

Básicamente, es una enorme mesa, pero los cambios se registran como XML en un campo de cadena.

Editar:

no tenía problemas con el cambio de nombres de columna, ya que cada cambio es una cadena XML.
La mayoría de las veces que tuve que cavar en la historia, la pregunta era "quién y cuándo cambiado eso ni un registro en particular", por lo que podría seleccionar pequeño número de registros con el mismo ID.
El problema con este enfoque es si necesita encontrar todos los registros donde se produjo algún valor. Requiere búsqueda de texto completo en toda la tabla y eso es muy lento.
Necesita analizar posibles escenarios de búsqueda y luego elegir la mejor solución.

Hay una cosa más a tener en cuenta: los registros del historial nunca se modificarán, por lo que puede tener otra base de datos que pueda mantener una copia de los registros del historial indexados para realizar búsquedas rápidas. Cree un servicio automático que de vez en cuando copie los registros del historial de la base de datos en vivo.

+0

La información fue útil, pero todavía tengo el problema de que si cambio el nombre de la columna de una tabla, no tendré manera de saber lo que era antes, así que puedo realizar búsquedas (a menos que realice un cambio de nombre masivo en la tabla de historial). Esto significa que tendré que mantener un registro de cambio de nombres de columna. En cuanto a la necesidad, estoy de acuerdo. Es una "característica muy importante" que apenas se usa. El problema es que, cuando se necesita, generalmente se debe a un caso judicial que da como resultado el cambio de manos. –

+0

La opción XML no es muy buena para mí, ya que los cambios realizados en las tablas deberán estar disponibles a través de una pestaña, de modo que en cualquier momento, cualquier usuario podrá ver quién cambió qué. –

Cuestiones relacionadas