Pattern per il versioning dei dati relazionali in un database MySQL?


12

Sto cercando di trovare un approccio per un progetto, in cui un utente può modificare i record ed essere in grado di vedere le versioni precedenti di tali record. Ecco uno schema di esempio semplificato, usando un elenco:

TABLE list (
  id int auto_increment primary key,
  user_id int, 
  title varchar(255)
);

TABLE list_tasks (
  id int auto_increment primary key,
  list_id int,
  title varchar(255),
  order int,
  is_complete tinyint
);

Quindi un utente può entrare e apportare diverse modifiche all'elenco (ad esempio, aggiungere o rimuovere attività, riordinare attività, contrassegnarne alcune complete, rinominarne alcune, ecc.), Quindi salvarle. A questo punto, vorrei generare una "versione 2" dell'elenco e delle attività e far sì che possano visualizzare le versioni precedenti, ma quando accedono all'elenco ottengono sempre l'ultima versione.

Esiste un approccio / modello di progettazione comune per gestire i dati di versioning in questo modo in un database MySQL?


Si noti che sono librerie per questo. Ad esempio, se si utilizza Hibernate, esiste Hibernate Envers. Quindi, se hai un framework che gestisce DAO per te, prova a cercare se c'è qualcosa del genere.
Walfrat,

Risposte:


9

È abbastanza comune volerlo fare in un db. Anche se ci stai dando una svolta in quanto vuoi tenere traccia di una revisione per un elenco di elementi.

Un modo per farlo potrebbe essere quello di modificare la struttura come

Alter table lists add revision_id integer;
Alter table list_tasks add revision_id integer;

Create Table revisions
{
   id int autoincrement... (revision id)
   list_id int...
   revdate datetime...
}

Quando l'utente salva il proprio elenco, crea una nuova revisione nella revisionstabella sopra e assegna quel valore agli elementi dell'elenco list_taskse quindi all'ID di revisione listsper contrassegnare quell'id come revisione "corrente". Quando l'utente modifica gli elementi, non modificare gli elementi esistenti, ma piuttosto inserirne di nuovi con un nuovo ID di revisione e aggiornare la listtabella con quella revisione per contrassegnarla come quella corrente.

Quindi per elencare gli elementi correnti, elencare gli elementi dall'ID di revisione corrente specificato nella liststabella. Per sfogliare le versioni precedenti, è possibile ottenere un elenco di revisioni precedenti degli elenchi dalla tabella delle revisioni e quindi elencare i singoli elementi in base a tale ID.


5

Questa soluzione utilizza una tabella di controllo separata. Ha pro e contro. Puoi preferire eliminare i vecchi record dalla tabella principale. Il miglioramento delle prestazioni può essere trascurabile.

Aggiungi i seguenti campi a ciascuna tabella controllata:

AddUserID      int <whatever your system uses>
AddDateTime    datetime
UpdateUserID   int <whatever your system uses>
UpdateDateTime datetime
CurrentVersion int
IsDeleted      bit

Dovrai aggiornare questi campi ogni volta che cambiano i dati. CurrentVersion viene incrementato di 1 (potrebbe essere usato come un modo per bloccare un record, ma questa è un'altra domanda.) IsDeleted fornisce un "soft delete" in modo che possa essere referenziato in futuro.

Tabelle di controllo separate Ogni tabella deve avere una versione _Archive o _History corrispondente della tabella. Probabilmente non è necessario indicizzarli allo stesso modo. Ovviamente non verrà applicato un singolo campo chiave primaria. Dovresti essere in grado di creare una chiave composita fuori dal campo ID e UpdateDateTime.

Utilizzando un trigger (questo risolverà le modifiche apportate all'interno o all'esterno del codice. Puoi decidere se funziona in base alla tua situazione.) O altri codici, quando un record viene aggiunto, aggiornato o eliminato, una copia del record viene inserita nell'archivio / tabella cronologica. Vengono mantenute tutte le versioni e gli altri campi di controllo. Questo ti dirà cosa hanno fatto gli utenti e quando. La tabella può essere confrontata con se stessa per vedere quando è stato modificato un record o per vedere le tendenze.

Ho visto questo lavoro bene negli ultimi anni. Mi piacerebbe conoscere gli svantaggi che potrei non prendere in considerazione.


Sto valutando questo oltre a quelli di GrandMasterB, entrambi sono buoni e quale usare dipende da maggiori dettagli sulle esigenze specifiche.
junky

-2

Suggerirei di leggere questo articolo ben dettagliato.

https://blog.jondh.me.uk/2011/11/relational-database-versioning-strategies/comment-page-1/#comment-373850

Un altro approccio consiste nell'avere una colonna version_id nella tabella e un flag 'corrente' che specifica quale riga è quella corrente. Ogni volta che è necessario un aggiornamento, è possibile inserire una nuova riga e impostare il flag 'corrente' della versione esistente su 0 / false e la riga appena aggiunta su 1.

In questo modo è possibile creare una vista che mostra solo quelli con il set di flag corrente.

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.