En un proyecto en el que estoy trabajando, cada cambio en las filas en algunas tablas de la base de datos debe ser rastreado para una auditoría o reversión posterior. Debe ser fácil encontrar quién modificó la fila, desde qué dirección IP y cuándo, y poder restaurar la versión anterior.
Lo mismo se utiliza, por ejemplo, por Stack Exchange. Cuando cambio la pregunta de otra persona, es posible descubrir que la cambié y revertir los cambios.
¿Cuál es la técnica general utilizada para almacenar cada cambio en un objeto en una base de datos , dado que mi esquema actual tiene principalmente las mismas propiedades (a continuación) que una aplicación comercial promedio?
- Los objetos tienen un tamaño relativamente pequeño: puede haber algunos,
nvarchar(1000)
por ejemplo, pero no grandes cantidades de datos binarios, este se almacena directamente en el disco y se accede directamente, y no a través de Microsoft SQLfilestream
, - La carga de la base de datos es bastante baja y toda la base de datos es manejada por una máquina virtual en un servidor,
- El acceso a las versiones anteriores no tiene que ser tan rápido como el acceso a la última versión, pero debe estar actualizado¹ y no demasiado lento².
<tl-dr>
Pensé en los siguientes casos, pero no tengo experiencia real con ese tipo de escenarios, por lo que escucharía las opiniones de otros:
Almacene todo en la misma tabla, distinguiendo las filas por ID y versión. En mi opinión, es muy estúpido y dolerá tarde o temprano en el nivel de rendimiento. Con este enfoque, también es imposible establecer un nivel de seguridad diferente para los últimos elementos y el seguimiento de versiones. Finalmente, cada consulta sería más complicada de escribir. En realidad, para acceder a los datos actualizados, me vería obligado a agrupar todo por ID y recuperar, en cada grupo, la última versión.
Almacene la última versión en una tabla y, en cada cambio, copie la versión obsoleta en otra tabla en otro esquema. La falla es que siempre almacenamos todos los valores, incluso si no cambiaron. Establecer valores sin cambios en
null
no es una solución, ya que también debo rastrear cuándo se cambia el valor hacianull
o desdenull
.Almacene la última versión en una tabla y la lista de propiedades modificadas con sus valores anteriores en otra tabla. Esto parece tener dos defectos: el más importante es que la única forma de ordenar tipos heterogéneos de valores anteriores en la misma columna es tener un
binary(max)
. El segundo es que, creo, sería más difícil usar dicha estructura cuando se muestran las versiones anteriores al usuario.Haga lo mismo que en dos puntos anteriores, pero almacene las versiones en una base de datos separada. En cuanto al rendimiento, puede ser interesante para evitar ralentizar el acceso a las últimas versiones al tener las versiones anteriores en la misma base de datos; Aún así, creo que es una optimización prematura y debe hacerse solo si hay una prueba de que tener versiones anteriores y más recientes en la misma base de datos es un cuello de botella.
</tl-dr>
¹ Por ejemplo, sería inaceptable almacenar los cambios en un archivo de registro, como se hace para los registros HTTP, y vaciar los datos del registro a la base de datos por la noche cuando la carga del servidor es más baja. La información sobre las diferentes versiones debe estar disponible de forma inmediata o casi inmediata; Un retraso de unos segundos es aceptable.
² No se accede a la información con mucha frecuencia y solo por un grupo específico de usuarios, pero aún así, sería inaceptable forzarlos a esperar 30 segundos para que se muestre la lista de versiones. Nuevamente, un retraso de unos segundos es aceptable.