sql >> Base de Datos >  >> RDS >> Mysql

¿Registro de auditoría para datos de productos?

Sus datos de auditoría deben almacenarse por tabla, en lugar de todos en un solo lugar. Lo que haría es crear una tabla de auditoría para cada una de las tablas que desea rastrear y crear disparadores para crear un registro en la tabla de auditoría para cualquier operación de manipulación de datos en la tabla auditada.

Definitivamente es recomendable deshabilitar DELETE operaciones en los items y item_options tablas - agregue banderas como item_active y item_option_active para que pueda borrarlos en su lugar. Esta es una práctica normal en situaciones en las que hace cosas como almacenar facturas que hacen referencia a productos pedidos en el pasado y necesita los datos para fines de informes históricos, pero no para el uso diario.

Sus tablas de auditoría no son algo que deba usar para hacer referencia a datos antiguos, su modelo de datos normal debe admitir simplemente "ocultar" datos antiguos donde es probable que todavía se usen, y almacenar múltiples versiones de datos que cambiarán con el tiempo.

Para la auditoría, también es útil almacenar el nombre de usuario del último usuario para modificar un registro dado; cuando se usa desde una aplicación web, no puede usar el USER() de MySQL. función para obtener cualquier información útil sobre quién ha iniciado sesión. Agregar una columna y completarla significa que puede usar esa información en sus activadores de auditoría.

Nota: Supongo que no permitirá que se cambien los ID de elementos en condiciones normales; eso haría que su sistema de auditoría fuera más complejo.

Si agrega indicadores activos y datos de la última modificación a sus tablas, se verán algo así como:

Tabla de artículos:

mysql> desc items;
+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| item_id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| item_name        | varchar(100) | YES  |     | NULL    |                |
| item_description | text         | YES  |     | NULL    |                |
| item_active      | tinyint(4)   | YES  |     | NULL    |                |
| modified_by      | varchar(50)  | YES  |     | NULL    |                |
+------------------+--------------+------+-----+---------+----------------+

Tabla de opciones de artículos:

mysql> desc item_options;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| option_id     | int(11)      | NO   | PRI | NULL    | auto_increment |
| item_id       | int(11)      | YES  | MUL | NULL    |                |
| option_name   | varchar(100) | YES  |     | NULL    |                |
| option_price  | int(11)      | YES  |     | NULL    |                |
| option_active | tinyint(4)   | YES  |     | NULL    |                |
| modified_by   | varchar(50)  | YES  |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+

Sus tablas de auditoría necesitan almacenar cuatro piezas adicionales de información:

  • ID de auditoría:este ID solo es único para el historial de esto tabla, no es un valor global
  • Cambio realizado por:el usuario de la base de datos que realizó el cambio
  • Cambiar fecha/hora
  • Tipo de acción:INSERT o UPDATE (o DELETE si lo estuvieras permitiendo)

Tus tablas de auditoría deberían verse así:

Tabla de auditoría de artículos:

mysql> desc items_audit;
+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| audit_id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| item_id          | int(11)      | YES  |     | NULL    |                |
| item_name        | varchar(100) | YES  |     | NULL    |                |
| item_description | text         | YES  |     | NULL    |                |
| item_active      | tinyint(4)   | YES  |     | NULL    |                |
| modified_by      | varchar(50)  | YES  |     | NULL    |                |
| change_by        | varchar(50)  | YES  |     | NULL    |                |
| change_date      | datetime     | YES  |     | NULL    |                |
| action           | varchar(10)  | YES  |     | NULL    |                |
+------------------+--------------+------+-----+---------+----------------+

Tabla de auditoría de opciones de artículos:

mysql> desc item_options_audit;
+---------------+--------------+------+-----+---------+----------------+
| Field         | Type         | Null | Key | Default | Extra          |
+---------------+--------------+------+-----+---------+----------------+
| audit_id      | int(11)      | NO   | PRI | NULL    | auto_increment |
| option_id     | int(11)      | YES  |     | NULL    |                |
| item_id       | int(11)      | YES  |     | NULL    |                |
| option_name   | varchar(100) | YES  |     | NULL    |                |
| option_price  | int(11)      | YES  |     | NULL    |                |
| option_active | tinyint(4)   | YES  |     | NULL    |                |
| modified_by   | varchar(50)  | YES  |     | NULL    |                |
| change_by     | varchar(50)  | YES  |     | NULL    |                |
| change_date   | datetime     | YES  |     | NULL    |                |
| action        | varchar(10)  | YES  |     | NULL    |                |
+---------------+--------------+------+-----+---------+----------------+

No utilice claves foráneas en sus tablas de auditoría; las filas en las tablas de auditoría no son filas secundarias de los registros que están auditando, por lo que las claves externas no sirven para nada.

Disparadores

Nota: MySQL no admite activadores de tipo de instrucción múltiple, por lo que necesita uno para cada INSERT , UPDATE y DELETE (si corresponde).

Tus disparadores simplemente necesitan INSERT todo lo NEW valores en la tabla de auditoría. Las definiciones de activación para los items la tabla podría ser:

/* Trigger for INSERT statements on the items table */
CREATE DEFINER=`root`@`localhost` TRIGGER trigger_items_insert_audit 
AFTER INSERT ON items 
  FOR EACH ROW BEGIN
    INSERT INTO items_audit (
                  item_id, item_name, item_description, 
                  item_active, modified_by, change_by,  
                  change_date, action
                ) VALUES (
                  NEW.item_id, NEW.item_name, NEW.item_description,  
                  NEW.item_active, NEW.modified_by, USER(),  
                  NOW(), 'INSERT'
                ); 
  END;

/* Trigger for UPDATE statements on the items table */
CREATE DEFINER=`root`@`localhost` TRIGGER trigger_items_update_audit 
AFTER UPDATE ON items 
  FOR EACH ROW BEGIN
    INSERT INTO items_audit (
                  item_id, item_name, item_description, 
                  item_active, modified_by, change_by,  
                  change_date, action
                ) VALUES (
                  NEW.item_id, NEW.item_name, NEW.item_description,  
                  NEW.item_active, NEW.modified_by, USER(),  
                  NOW(), 'UPDATE'
                ); 
  END;

Cree disparadores similares para item_options mesa.

Actualización:historial de datos en comercio electrónico

La auditoría que hicimos anteriormente le permitirá mantener un historial de cualquier tabla de base de datos dada, pero crea un almacén de datos que no es adecuado para el uso de datos a los que se debe acceder con regularidad.

En un sistema de comercio electrónico, mantener utilizable los datos históricos son importantes, de modo que puede cambiar los atributos mientras sigue presentando valores antiguos en ciertas situaciones.

Esto debe estar completamente separado de su solución de auditoría

La mejor manera de almacenar el historial es crear una tabla de historial para cada atributo que necesita ser almacenado históricamente. Esta pregunta de Stackoverflow tiene buena información sobre cómo mantener un historial de un atributo determinado .

En su situación, si solo le preocupa el precio y el título, crearía un prices tabla y un item_titles mesa. Cada uno tendría una clave externa para cualquiera de las item_options tabla o los items (las tablas maestras seguirían almacenando la tabla actual precio o título), y tendría el precio o título, con sus fechas de vigencia. Estas tablas deben tener permisos detallados (posiblemente basados ​​en columnas) para evitar actualizar el effective_from fechas y los valores reales una vez que se inserta el registro.

También debe usar la solución de auditoría anterior en estas tablas.