blawat
6.05.2010, 12:50:30
witam,
pytanie jak w temacie - dane w bazie maja byc wersjonowane z uwzglednieniem informacji o osobie dokunujacej operacji (dodanie/modyfikacja/usuniecie) jak najprosciej to zrealizowac?
JohnnyB
6.05.2010, 13:49:54
jeśli wystarczy sama informacja o operacji to najprościej będzie zrobić tabelę typu 'log' z kolumnami data,id_uzytkownika, tabela, id_rekordu itp. + jakiś opis, np. 'Usunięto rekord'. Można też zrobić funkcję, która porówna zawartość rekordu przed i po edycji i zapisywać co się zmieniło.
Zalety: proste, nie trzeba modyfikować innych tabel.
Inny sposób to utworzenie dodatkowej tabeli do każdej, która ma być wersjonowana i przenoszenie rekordów do 'archiwum'.
Zalety: w razie czego łatwo zrobić operację odwrotną i przywrócić np. omyłkowo skasowany rekord.
Temat jest interesujący i sam jestem ciekaw jak to się robi w dużych projektach.
blawat
6.05.2010, 14:47:24
ja poszdlem wlasnie w strone "druga" tzn dla kazdej tabeli dorobilem tabele z sufixem _arch w ktorej dolozylem 3 kolumny (id, type, ctime) odpowiednio primary key, type - okresa rodzaj operacji na rekordzie (dodanie/modyfikacja/usuniecie), ctime (current timestamp). we wszytskich tabelach mam informacje o uzytkowniku. wiec dane te sa propagowane
na kazda tabele nalozylem triggery na operacje insert, update, delete tak ze automaycznie po jakichkowliek operacjach zmieniajacych dane sa one "kopiowane do swoich tabel _arch
problemem jest tylko operacja delete gdyz sam trigger niczego nie zalatwia a jedynie "skopiuje" nam dane do tabeli _arch. obeszlem to przez napisanie procedury i teraz wyjatkowo wszystkie kasowania odbywaja sie przez procedury ktora jako parametr przyjmuje id kasowanego rekordu oraz id uzytkownika) nastepnie w wielkim uproszczeniu procedura kasuje dane z tabli "glownej" - trigger te dane "przenosi" do tabeli _arch i procedura nastepnie w tabeli _arch ustawia juz prawidlowo uzytkownika ktory dokonal modyfikacji
jak ktos chce jakies dokladniejsze sczegoly to pisac na priva
darko
6.05.2010, 15:18:22
Jest jeszcze możliwość dodania pięciu pól do danej tabeli:
- status_rekordu - tinyint(1)
- data_dodania - datetime
- login_dodania - varchar(55)
- data_modyfikacji - timestamp z domyślną wartością - CURRENT_TIMESTAMP
- login_modyfikacji - varchar(55)
Na podstawie tych pięciu pól mamy dostęp do pełnej historii zmian danego rekordu.
blawat
6.05.2010, 16:22:50
tak naprawde to starcza 3 pola - status, user i czas
bubel jest tylko jeden ze przy wszystkich zapytaniach trzeba zapewne uwzgledniac pomijanie rekordow "powersjonowaniu" :/ - mozna oczywiscie zrobic widok z ktory pominie dane wersjonowane ale nie wiem czy takie cos kogos zadowoli - chyba wolalbym miec archiwum gdzies osobno aczkolwiek przyznam sie ze juz takie rozwiazanie stosowalem
webmaniak
18.05.2014, 16:28:15
Witam, ciekawy temat, zatem spytam, czy coś się zmieniło w kwestii wersjonowania baz danych? Czy jest do tego narzędzie dla bazy MySql? prócz tego:
http://trojniak.net/Article/dbdeploy?
mrygiel
30.05.2014, 11:59:58
Wszystko zależy od konkretnych potrzeb.
Najprościej jest zrobić trigger, który będzie wykonywany zaraz po operacji (dodania, edycji, usunięcia danych). Jego zadaniem będzie zebranie informacji, które są modyfikowane w bazie (NEW.pole1, NEW.pole2...) i zapisanie ich do osobnej tabeli "dziennika". Tu mamy pole manewru, bo możemy dane porównywać (czy OLD.pole1 jest różne od NEW.pole1) i zapisywać tylko informacje zmodyfikowane ( A ), a możemy też robić migawkę z danej chwili i wpisywać kopię całego rekordu ( B ).
Ad. A ) Jeśli zapisujemy jedynie zmiany (czyli tworzymy dziennik zmian - jedynie do wglądu co i kiedy, oraz ewentualnie przez kogo zostało zmodyfikowane), to struktura takiej tabeli np. może być taka: id INT, rodzaj_operacji ENUM('dodanie','edycja','usuniecie'), nazwa_kolumny VARCHAR(255), wartosc TEXT, data_wpisu DATETIME, wpisal_id INT. Dobrą praktyką jest też dodanie kolumny zawierającej odnośnik do poprzedniego rekordu ( np. ostatnie_id INT ) - mając takie dane łatwiej się po historii poruszać.
Ad. B ) W przypadku drugiego wariantu - struktura tabeli dziennika może być kopią tabeli, z której dane chcemy archiwizować + info kto i kiedy wpisał ( wpisal_id, rodzaj_operacji, data_wpisu, ostatnie_id ). To podejście jest mniej oszczędne z puntu widzenia przestrzeni dyskowej, bo zapisujemy wszystkie rekordy nawet jak tylko była zmiana w jednej kolumnie + w każdym momencie mamy ostatni wpis z tabeli głównej także w dzienniku, ale za to w prosty i wydajny sposób możemy zobaczyć, jak wyglądał komplet danych w dowolnej chwili "życia" bazy. Gdybyśmy chcieli to zrobić tylko na podstawie dziennika zmian, to trzeba by te dane w locie odbudowywać przeczesując całą historię wstecz, a to może być trudne i kosztowne na dużych danych.
Z triggerem jest jednak o tyle problem, że trudno do niego wszczepić jakieś dodatkowe informacje (w sensie: poza tym, co jest modyfikowane) - tą informacją może być właśnie np. ID osoby zalogowanej na stronie. Zazwyczaj na stronie internetowej osoby zalogowane współdzielą konto, które jest używane przez skrypt do połączenia się do bazy danych toteż jak 2 różne osoby coś zmodyfikują to chcielibyśmy wiedzieć kto tego dokonał, z tego też względu lepiej opracować taki mechanizm zapisu bezpośrednio w skrypcie, jednak to już wymaga więcej pracy. Alternatywnie - można te dodatkowe informacje wstrzykiwać za pomocą zmiennych (np. na początku działania strony możemy wykonać zapytanie: "SELECT @wpisujacy_id := 51215" a potem w triggerze się do tego odwołać - nie polecam jednak tej metody bo robiąc to nieuważnie możemy stracić kontrolę nad tym, co będzie zapisywane w bazie.
Webmaniak: opisywane narzędzie to nieco inny temat, bo w tym wątku rozmawialiśmy o wersjonowaniu samych danych - a podany przez Ciebie link dotyczy wersjonowania schematu bazy.
webmaniak
15.06.2014, 09:45:26
No ok, podany link dotyczy wersjonowania schematu bazy danych, ale mi właśnie zależy na znalezieniu narzędzia/sposobu do wersjonowania bazy danych - schematu + danych - czyli jednym słowem wszystkiego

Dzięki za opis, przeanalizuję go