Mysql
 sql >> Database >  >> RDS >> Mysql

Archivia tutte le modifiche ai dati con ogni dettaglio (come Stackoverflow)

Ci ho pensato per un po' e posso pensare solo a due modi per farlo. Entrambi possono funzionare in modo completamente trasparente se realizzati in un livello/modello di dati astratto.

A proposito, esiste un'implementazione per i dati di tabella "versionabili" nella dottrina del mappatore ORM. Vedi questo esempio nei loro documenti . Forse si adatta alle tue esigenze, ma non alle mie. Sembra eliminare tutti i dati della cronologia quando viene eliminato il record originale, rendendolo non realmente sicuro per la revisione.

Opzione A:avere una copia di ogni tabella per contenere i dati di revisione

Supponiamo che tu abbia una semplice tabella dei contatti:

CREATE TABLE contact (
    id INT NOT NULL auto_increment,
    name VARCHAR(255),
    firstname VARCHAR(255),
    lastname VARCHAR(255),
    PRIMARY KEY (id)
)

Dovresti creare una copia di quella tabella e aggiungere i dati di revisione:

CREATE TABLE contact_revisions (
    id INT NOT NULL,
    name VARCHAR(255),
    firstname VARCHAR(255),
    lastname VARCHAR(255),
    revision_id INT auto_increment,
    type ENUM('INSERT', 'UPDATE', 'DELETE') NOT NULL,
    change_time DEFAULT current_timestamp,
    PRIMARY KEY(revision_id)
)

Tieni traccia di INSERT e UPDATE usando AFTER trigger. Ad ogni nuova revisione dei dati nell'originale, inserire una copia dei nuovi dati nella tabella delle revisioni e impostare la modifica type correttamente.

Per registrare un DELETE revisionalmente sicuro devi anche inserire una nuova riga nella tabella della cronologia! Per questo dovresti usare un BEFORE DELETE attivare e memorizzare gli ultimi valori prima che vengano eliminati. Altrimenti dovrai rimuovere ogni NOT NULL vincolo anche nella tabella della cronologia.

Alcune note importanti su questa implementazione

  • Per la tabella della cronologia devi eliminare ogni UNIQUE KEY (qui:la PRIMARY KEY ) dalla tabella delle revisioni perché avrai la stessa chiave più volte per ogni revisione dei dati.
  • Quando ALTER lo schema e i dati nella tabella originale tramite un aggiornamento (ad es. aggiornamento del software) è necessario assicurarsi che gli stessi dati o le correzioni dello schema vengano applicate anche alla tabella della cronologia e ai suoi dati. In caso contrario, si verificheranno problemi quando si ripristina una revisione precedente di un set di record.
  • In un'implementazione nel mondo reale vorresti sapere quale utente ha modificato i dati. Per avere tale sicurezza dal punto di vista della revisione, un record utente non dovrebbe mai essere eliminato dalla tabella degli utenti. Dovresti semplicemente disattivare l'account con un flag.
  • Di solito, una singola azione dell'utente coinvolge più di una tabella. In un'implementazione nel mondo reale, dovresti anche tenere traccia di quali modifiche in più tabelle appartengono a una singola transazione utente e anche in quale ordine. In un caso d'uso reale vorresti annullare tutte le modifiche di una singola transazione insieme, in ordine inverso. Ciò richiederebbe una tabella di revisione aggiuntiva che tenga traccia degli utenti e delle transazioni e tenga una relazione libera con tutte quelle singole revisioni nelle tabelle della cronologia.

Vantaggi:

  • completamente nel database, indipendente dal codice dell'applicazione. (beh, non quando il monitoraggio delle transazioni degli utenti è importante. ciò richiederebbe una logica al di fuori dell'ambito della singola query)
  • tutti i dati sono nel loro formato originale, nessuna conversione di tipo implicita.
  • buona performance sulla ricerca nelle revisioni
  • facile ripristino. Basta fare un semplice INSERT .. ON DUPLICATE KEY UPDATE .. istruzione sulla tabella originale, utilizzando i dati della revisione di cui si desidera eseguire il rollback.

Pregi:

  • Difficile da implementare manualmente.
  • Difficile (ma non impossibile) automatizzare quando si tratta di migrazioni di database/aggiornamenti di applicazioni.

Come già affermato sopra, dottrine versionable fa qualcosa di simile.

Opzione B:avere una tabella di registro delle modifiche centrale

prefazione:cattiva pratica, mostrata solo a scopo illustrativo dell'alternativa.

Questo approccio si basa fortemente sulla logica dell'applicazione, che dovrebbe essere nascosta in un livello/modello di dati.

Hai una tabella della cronologia centrale che tiene traccia di

  • Chi l'ha fatto
  • quando
  • modifica, inserisci o elimina
  • quali dati
  • in quale campo
  • di quale tabella

Come nell'altro approccio, potresti anche voler tenere traccia di quali singole modifiche ai dati appartengono a una singola azione/transazione dell'utente e in quale ordine.

Vantaggi:

  • non è necessario mantenere la sincronizzazione con la tabella originale quando si aggiungono campi a una tabella o si crea una nuova tabella. si ridimensiona in modo trasparente.

Pregi:

  • cattiva pratica utilizzando un valore semplice =archivio chiavi nel database
  • Rendimento della ricerca scadente, a causa di conversioni di tipo implicite
  • può rallentare le prestazioni complessive dell'applicazione/database, quando la tabella della cronologia centrale diventa un collo di bottiglia a causa di blocchi di scrittura (questo vale solo per motori specifici con blocchi di tabella, ad esempio MyISAM)
  • È molto più difficile implementare i rollback
  • Possibili errori di conversione dei dati/perdita di precisione a causa della conversione di tipo implicita
  • non tiene traccia delle modifiche quando accedi direttamente al database da qualche parte nel tuo codice invece di utilizzare il tuo modello / livello dati e dimentica che in questo caso devi scrivere manualmente nel registro delle revisioni. Può essere un grosso problema quando si lavora in team con altri programmatori.

Conclusione:

  • Opzione B può essere molto utile per le piccole app come un semplice "drop-in" quando serve solo per registrare le modifiche.
  • Se vuoi tornare indietro nel tempo ed essere in grado di confrontare facilmente le differenze tra le revisioni storiche 123 alla revisione 125 e/o ripristinare i vecchi dati, quindi Opzione A è la strada più difficile da percorrere.