Modi per avere una cronologia delle modifiche alle voci del database


21

Quali sono i modi per consentire il controllo delle versioni delle voci del database (dati)?

Pensa alle capacità dei sistemi di gestione dei contenuti per ripristinare le modifiche agli articoli.

Quali sono i loro pro / contro?


1
Cosa vuoi esattamente la versione? Lo schema o i dati?
tdammers,

1
Voglio versioni dei dati. Per rimanere nell'esempio di cms, diciamo le versioni degli articoli .
Matcauthon,

Potresti voler esaminare Datomic.
dan_waterworth,

Risposte:


19

Esistono fondamentalmente due approcci: una tabella di controllo, con tutti i valori precedenti memorizzati in essa, o includere una data di inizio / fine come parte della tabella e tutti gli aggiornamenti creano un nuovo record mentre si chiude quello vecchio.

Aggiornamento: SQL Server 2016 supporta questo come un / tipo di tabella modello di progettazione - https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-2017


4
Quindi il primo approccio potrebbe essere più scalabile. Poiché i dati "archiviati" saranno raramente accessibili, la progettazione del database potrebbe essere ottimizzata. E il tavolo di lavoro rimane piccolo. A seconda della complessità, dovrebbe anche essere possibile salvare solo differenze. È consigliabile utilizzare il modello di ricordo ?
Matcauthon,

1
Ciò dipenderà dal tuo utilizzo, potrebbe essere sufficiente utilizzare i trigger per popolare la tabella / e quindi fornire un modo per scegliere cosa e fino a che punto eseguire il rollback.
jmoreno,

Hai un refuso nella tua risposta (lo scalpiccio dovrebbe essere un modello)
geocodezip,

7

Un'idea è quella di utilizzare "Database di solo inserimento". L'idea di base è che non si eliminano o si aggiornano mai i dati di fila .

Ogni tabella che deve essere tracciata avrà due datetimecolonne frome to. Iniziano con il valore NULLin ciascuno (dall'inizio del tempo alla fine del tempo). Quando devi "cambiare" la riga aggiungi una nuova riga e allo stesso tempo aggiorni la toriga precedente Nowe fromla riga a cui stai aggiungendo Now.

Per informazioni più dettagliate guarda:

Questa tecnica è chiamata AuditTrailper gestire i dati legacy e i suoi negozi archiviano la cronologia delle modifiche.

Sembra che la domanda di questa natura sia già stata pubblicata:


Purtroppo questa domanda sembra essere stata cancellata :(
Douglas Gaskell,

Nessun problema, ecco il link . Un altro suggerimento di design in link
Yusubov,

2

Penso che puoi usare i trigger per ogni tabella e mantenere i dati in _history (o puoi dare qualsiasi nome) e su ogni inserimento, aggiornamento, cancellazione sulla tabella principale attiverà il tuo trigger e puoi salvare i dettagli in questa tabella. Meccanismo di trigger è disponibile anche con il database SQLite se ne usi uno.

Questo meccanismo è utile anche per grandi progetti. In questa tabella è possibile registrare le informazioni dell'utente che ha apportato le modifiche insieme al timestamp delle modifiche. è quindi possibile ripristinare la tabella in uno qualsiasi dei timestamp corrispondenti alle proprie esigenze.

Ogni database ha il suo modo di scrivere e trigger di codice. Se si utilizza SQLite, visitare SQLite.org per la sintassi. Per altri database è possibile visitare i loro siti ufficiali.


1

Probabilmente sei a conoscenza del motore db Sqlite . L'intero db viene salvato in un singolo file. L'API supporta anche i file system virtuali, quindi in pratica puoi organizzare l'archiviazione ovunque e con qualsiasi formato, basta rispondere alle operazioni di lettura e scrittura a determinati offset di file. Le possibili applicazioni per questo potrebbero essere la crittografia, la compressione e così via. La parte migliore di questo è che il livello contenitore non dovrebbe sapere nulla di database, formato di file sql o sqlite, basta obbedire ai callback xRead e xWrite.

Una delle idee era quella di implementare le funzionalità della macchina del tempo. Quindi qualsiasi operazione xWrite salva ogni segmento che sovrascriverà nella cronologia "annulla" e l'utente può scegliere una data nel passato per vedere cosa conteneva il db (probabilmente modalità di sola lettura). Non ho ancora un esempio funzionante (si è discusso al riguardo nella mailing list di sqlite), ma probabilmente altri motori forniscono API VFS, quindi è possibile fare qualcosa di simile. E una volta implementato, dovrebbe essere compatibile con strutture di database di qualsiasi complessità.


Cosa pensi sia questo approccio scalabile per progetti più grandi?
Matcauthon,

Penso che questo potrebbe aggiungere un sovraccarico di dati di grandi dimensioni per le modifiche ai big data (ovviamente poiché ogni singola modifica dovrebbe essere salvata, sebbene la compressione per la versione precedente possa aiutare). A parte questo, dal punto di vista del tuo schema, purché funzioni per due tabelle, funziona per venti.
Guarda il

1

Il metodo utilizzato per le voci del database di controllo delle versioni è utilizzare una tabella di controllo. La tabella ha uno schema lungo le linee di:

Seq      - Int      ' Unique identifier for this table
Event    - Char     ' Insert / Update / Delete
TblName  - Char     ' Table that had field value changed
FldName  - Char     ' Field that was changed
KeyValue - Char     ' delimited list of values for fields that make up the PK of table changed
UsrId    - Char     ' User who made the change
OldValue - Char     ' Old value (converted to character)
NewValue - Char     ' New value (converted to character)
AddTs    - DateTime ' When the change was made

Abbiamo quindi i trigger su Inserisci / Aggiorna / Elimina delle tabelle che vogliamo monitorare.

Professionisti:

  • Tutti i dati sono in una tabella
  • Può essere configurato per tracciare tutti i campi o campi specifici in una tabella
  • Controllo delle versioni facile da mostrare su ogni campo per una tabella

Contro:

  • La presenza di tutte le informazioni di controllo in una tabella genera un numero estremamente elevato di record
  • Sono necessari molti trigger

0

Sto facendo una versione di questo ora. per ogni record ho una data inserita, una data modificata e un flag booleano Record attivo. Per l'inserimento iniziale, le date inserite e modificate sono entrambe impostate su Now () (questo esempio è in Access) e il flag Record attivo è impostato su true. quindi se modifico quel record copio tutto in un nuovo record, cambiando i campi che l'utente sta cambiando, lascio la data di inserimento uguale all'originale e cambio la data modificata su Now (). Poi capovolgo il flag Active Record del record originale su falsee il nuovo record su true. Ho anche un campo per ModifiedRecordsParentID in cui salvo l'identità del record originale.

Quindi, se ho anche bisogno di interrogare, posso solo restituire i record dove ActiveRecord = truee otterrò solo le informazioni più aggiornate.


Non c'è bisogno della ActiveRecordbandiera. La riga MAX (*) dovrebbe essere sempre il record corrente. Il ripristino di una versione precedente inserisce nuovamente detta riga nella tabella.
inverti il

Non ero sicuro di come far funzionare la selezione, ma ora che lo stai chiamando ci sto pensando e ho un'idea, hmmmm
Brad

Di solito MAX (nome_colonna) seleziona il valore più grande nella colonna della tabella. Per selezionare l'intera riga, un semplice select top 1 order by id descendingfarà.
inverti l'

Sì, funziona per un semplice record singolo, ma la mia tabella era una raccolta di record figlio che avrebbe dovuto essere selezionata immediatamente ma avrebbe potuto essere modificata individualmente. Solo un po 'più complesso.
Brad

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.