Cuando vi la implementación del "historial de registros" - versiones, al lado del programa trabajando con la base de datos SQL. Antes de cambiar el registro, la versión anterior se obtuvo de la base de datos, se escribió en XML y la cadena XML resultante se escribió en una tabla de versión separada.
Inicialmente, en su programa, planeaba realizar el control de versiones algún tiempo después, no había necesidad urgente. Recuerdo que había un deseo de usar el tipo de datos jsonb en algún lugar, tan pronto como pensé en una implementación simple y concisa de las versiones en el lado de SQL, no pude hacerlo. Solo una tabla de versión con 5 columnas y una función de activación en 3 líneas de código.
Describir la implementación de una tabla de versión no es suficiente, por lo que debe describir algunas tablas más, por ejemplo.
En casi todas las bases de datos, con raras excepciones, hay una tabla de usuarios: usuarios. Es útil almacenar el historial de cambios: versiones del usuario, por ejemplo, para que el usuario mismo pueda volver a la versión anterior.
Ejemplo de tabla de usuario:

Los dos últimos campos de la imagen son necesarios para la tabla de versiones, también pueden denominarse "autor de la versión" y "fecha de versión", pero, si lo desea, puede prescindir de ellos.
Tabla de versiones:

Función de disparo para guardar versiones:

Los primeros dos campos se rellenan desde el registro guardado OLD.changestamp y OLD.userid.
En la tabla de versiones, no solo se pueden almacenar las entradas de la tabla de usuarios, el tercer campo es el hash MD5 del nombre de la tabla versionada, convertida a uuid.
Los ejemplos describieron previamente una estructura muy simple, pero como regla, varios datos de referencia pueden tener tablas adicionales con una relación de uno a muchos.
Por ejemplo, la tabla "Grupos de usuarios".

Y la segunda tabla es "Usuarios del grupo", la composición del grupo son los usuarios del grupo.

Para no complicar el mecanismo simple de control de versiones, puede hacer una ligera duplicación de datos en la tabla de grupos, agregar un campo jsonb que repita la estructura de la tabla "Usuarios de grupo".

Para simplificar el trabajo con datos duplicados, puede realizar una función de activación adicional, con INSERTAR o ACTUALIZAR, llenando la tabla "Agrupar usuarios" desde el campo jsonb.

La duplicación descrita anteriormente solo es necesaria cuando se requiere obtener datos de la tabla con frecuencia y lo más rápido posible. Por ejemplo, si a menudo se realiza una consulta en la tabla "Usuarios del grupo" para determinar si un usuario es miembro del grupo Administradores. En otros casos, los datos se pueden obtener mediante consultas directamente desde el campo jsonb, y no utilizar una tabla duplicada.
El código de ejemplo completo está aquí.