In un progetto a cui sto lavorando, ogni modifica alle righe in alcune tabelle del database deve essere tracciata per ulteriore controllo o rollback. Deve essere facile trovare chi ha modificato la riga, da quale indirizzo IP e quando ed essere in grado di ripristinare la versione precedente.
La stessa cosa viene usata ad esempio da Stack Exchange. Quando cambio la domanda di qualcun altro, è possibile scoprire che l'ho modificata e ripristinare le modifiche.
Qual è la tecnica generale utilizzata per archiviare ogni modifica a un oggetto in un database , dato che il mio schema attuale ha principalmente le stesse proprietà (sotto) di un'app aziendale media?
- Gli oggetti hanno dimensioni relativamente ridotte: potrebbero essercene alcuni,
nvarchar(1000)
ad esempio, ma non enormi BLOB di dati binari, che vengono archiviati direttamente sul disco e accessibili direttamente e non tramite Microsoft SQLfilestream
, - Il carico del database è piuttosto basso e l'intero database è gestito da una macchina virtuale su un server,
- L'accesso alle versioni precedenti non deve essere veloce come l'accesso all'ultima versione, ma deve essere aggiornato¹ e non troppo lento².
<Tl-dr>
Ho pensato ai seguenti casi, ma non ho esperienza reale con questo tipo di scenari, quindi ascolterei le opinioni degli altri:
Memorizza tutto nella stessa tabella, distinguendo le righe per ID e versione. IMO, è seriamente stupido e farà male presto o tardi a livello prestazionale. Con questo approccio, è anche impossibile impostare un livello di sicurezza diverso per gli ultimi elementi e per la traccia delle versioni. Infine, ogni query sarebbe più complicata da scrivere. In realtà, per accedere ai dati aggiornati, sarei costretto a raggruppare tutto per ID e recuperare, in ciascun gruppo, l'ultima versione.
Archivia la versione più recente in una tabella e, ad ogni modifica, copia la versione obsoleta in un'altra tabella in un altro schema. Il difetto è che ogni volta archiviamo ogni valore, anche se non è cambiato. L'impostazione di valori invariati su
null
non è una soluzione, poiché devo anche tenere traccia di quando il valore viene modificato danull
o versonull
.Archivia l'ultima versione in una tabella e l'elenco delle proprietà modificate con i valori precedenti in un'altra tabella. Questo sembra avere due difetti: il più importante è che l'unico modo per ordinare tipi eterogenei di valori precedenti nella stessa colonna è avere un
binary(max)
. Il secondo è che, credo, sarebbe più difficile usare tale struttura quando si visualizzano le versioni precedenti all'utente.Fai la stessa cosa di due punti precedenti, ma archivia le versioni in un database separato. Per quanto riguarda le prestazioni, potrebbe essere interessante al fine di evitare di rallentare l'accesso alle ultime versioni avendo le versioni precedenti nello stesso database; tuttavia, credo che sia un'ottimizzazione prematura e deve essere fatto solo se c'è una prova che avere versioni più vecchie e più recenti nello stesso database è un collo di bottiglia.
</ TL-dr>
¹ Ad esempio, sarebbe inaccettabile archiviare le modifiche in un file di registro, come avviene per i registri HTTP, e scaricare i dati dal registro al database di notte quando il carico del server è più basso. Le informazioni sulle diverse versioni devono essere disponibili immediatamente o quasi immediatamente; è accettabile qualche secondo di ritardo.
² Le informazioni non sono accessibili molto frequentemente e solo da specifici gruppi di utenti, ma sarebbe inaccettabile costringerli ad attendere 30 secondi affinché venga visualizzato l'elenco delle versioni. Ancora una volta, è accettabile qualche secondo di ritardo.