Wzory dla wersjonowania danych relacyjnych w bazie danych MySQL?

12

Próbuję znaleźć podejście do projektu, w którym użytkownik może edytować rekordy i móc zobaczyć poprzednie wersje tych rekordów. Oto uproszczony przykładowy schemat z wykorzystaniem listy:

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
);

Tak więc użytkownik może wejść i dokonać kilku zmian na liście (tj. Dodać lub usunąć zadania, zmienić kolejność zadań, oznaczyć niektóre jako zakończone, zmienić nazwy niektórych itd.), A następnie zapisać je. W tym momencie chciałbym wygenerować „wersję 2” listy i zadań oraz umożliwić im przeglądanie poprzednich wersji, ale kiedy uzyskują dostęp do listy, zawsze otrzymują najnowszą wersję.

Czy istnieje wspólny wzorzec podejścia / projektowania do obsługi wersjonowania danych w ten sposób w bazie danych MySQL?

GSto
źródło
Zauważ, że są do tego bibliotekami. Na przykład, jeśli używasz Hibernacji, istnieje Hibernacja Envers. Więc jeśli masz jakieś frameworki do obsługi DAO, spróbuj poszukać czegoś takiego.
Walfrat

Odpowiedzi:

9

Często zdarza się, że chcesz to zrobić w db. Chociaż kładziesz na nim nacisk, ponieważ chcesz śledzić wersję listy przedmiotów.

Jednym ze sposobów na to może być zmiana struktury takiej jak

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...
}

Gdy użytkownik zapisze swoją listę, utwórz nową wersję w revisionspowyższej tabeli i przypisz tę wartość do elementów listy w, list_tasksa następnie do identyfikatora zmiany w, listsaby oznaczyć ten identyfikator jako „bieżącą” wersję. Gdy użytkownik edytuje elementy, nie edytuj istniejących elementów - zamiast tego wstaw nowe z nowym identyfikatorem wersji i zaktualizuj listtabelę z tą wersją, aby oznaczyć ją jako bieżącą.

Następnie, aby wyświetlić listę bieżących elementów, wypisz elementy z bieżącego identyfikatora zmiany określonego w liststabeli. Aby przeglądać poprzednie wersje, możesz uzyskać listę poprzednich wersji list z tabeli wersji, a następnie listę poszczególnych pozycji na podstawie tego identyfikatora.

Grandmaster B.
źródło
5

To rozwiązanie wykorzystuje osobną tabelę kontroli. Ma zalety i wady. Może wolisz wyeliminować stare rekordy z głównego stołu. Poprawa wydajności może być nieznaczna.

Dodaj następujące pola do każdej kontrolowanej tabeli:

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

Będziesz musiał zaktualizować te pola przy każdej zmianie danych. CurrentVersion zwiększa się o 1 (może to służyć jako sposób na zablokowanie rekordu, ale to inne pytanie.) IsDeleted zapewnia „miękkie usuwanie”, aby można było do niego odwoływać w przyszłości.

Oddzielne tabele kontroli Każda tabela powinna mieć odpowiednią wersję tabeli _Archive lub _History. Te prawdopodobnie nie muszą być indeksowane w ten sam sposób. Oczywiście jedno pole klucza podstawowego nie będzie miało zastosowania. Powinieneś być w stanie zrobić klucz złożony z pola ID i UpdateDateTime.

Za pomocą wyzwalacza (odniesie się to do zmian dokonanych w kodzie lub poza nim. Możesz zdecydować, czy to zadziała w twojej sytuacji). / tabela historii. Wszystkie wersje i inne pola kontroli są utrzymywane. Dzięki temu dowiesz się, co użytkownicy zrobili, kiedy. Tabelę można porównać do siebie, aby zobaczyć, kiedy rekord został zmieniony lub zobaczyć trendy.

Widziałem tę pracę dobrze w ciągu ostatnich kilku lat. Chciałbym usłyszeć o wadach, których być może nie rozważam.

JeffO
źródło
Głosuję za tym, podobnie jak GrandMasterB, oba są dobre, a który z nich zależy od więcej szczegółów na temat konkretnych potrzeb.
śmieciowe
-2

Proponuję przeczytać ten bardzo szczegółowy artykuł.

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

Innym podejściem jest posiadanie kolumny version_id w tabeli i flagi „bieżącej”, która określa, który wiersz jest bieżącym. Za każdym razem, gdy potrzebujesz aktualizacji, możesz wstawić nowy wiersz i ustawić flagę „bieżąca” istniejącej wersji na 0 / false, a nowo dodany wiersz na 1.

W ten sposób możesz utworzyć widok pokazujący tylko te z bieżącym zestawem flag.

Ehsan
źródło