9

Mam system CMS, który przechowuje dane w poprzek stołów tak:Przechowywanie historii zmian strony. Trochę podobnie jak robi dla korekt

Entries Table 
+----+-------+------+--------+--------+ 
| id | title | text | index1 | index2 | 
+----+-------+------+--------+--------+ 

Entries META Table 
+----+----------+-------+-------+ 
| id | entry_id | value | param | 
+----+----------+-------+-------+ 

Files Table 
+----+----------+----------+ 
| id | entry_id | filename | 
+----+----------+----------+ 

Entries-to-Tags Table 
+----+----------+--------+ 
| id | entry_id | tag_id | 
+----+----------+--------+ 

Tags Table 
+----+-----+ 
| id | tag | 
+----+-----+ 

jestem próbując wdrożyć system rewizyjną, trochę jak tak ma. Gdybym tylko robił to dla Entries Table, zamierzałem po prostu zachować kopię wszystkich zmian w tej tabeli w osobnej tabeli. Ponieważ muszę to zrobić dla co najmniej 4 tabel (tabela TAGS nie musi mieć poprawek), to nie wydaje się jak eleganckie rozwiązanie.

Jak byście to zrobili?

Proszę zauważyć, że Meta Stoły są modelowane w EAV (entity-attribute-value).

Z góry dziękuję.

Odpowiedz

8

Witam pracuję nad rozwiązaniem podobnego problemu, rozwiązuję go dzieląc moje tabele na dwie, tabelę kontrolną i tabelę danych. Tabela kontrolna będzie zawierała klucz podstawowy i odniesienie do tabeli danych, tabela danych będzie zawierała klucz automatycznej inkrementacji i klucz podstawowy tabeli sterującej jako klucz obcy.

przy stole wpisy jako przykład

Entries Table 
+----+-------+------+--------+--------+ 
| id | title | text | index1 | index2 | 
+----+-------+------+--------+--------+ 

staje

entries    entries_data 
+----+----------+ +----------+----+--------+------+--------+--------+ 
| id | revision | | revision | id | title | text | index1 | index2 | 
+----+----------+ +----------+----+--------+------+--------+--------+ 

kwerendy

select * from entries join entries_data on entries.revision = entries_data.revision; 

zamiast aktualizowania tabeli entries_data użyć instrukcji INSERT, a następnie zaktualizować wprowadzanie zmian w tabeli wpisów z nową wersją tabeli wpisów.

Zaletą tego systemu jest to, że można przejść do różnych wersji po prostu zmieniając właściwość rewizji w tabeli wpisów. Wadą jest aktualizacja zapytań. Obecnie integruję to w warstwie ORM, aby programiści nie martwili się o pisanie kodu SQL. Innym pomysłem, z którym borykam się, jest scentralizowana tabela zmian, z której korzystają wszystkie tabele danych. Umożliwi to opisanie stanu bazy danych za pomocą jednego numeru wersji, podobnie jak działa numer wersji subversion.

+0

Dlaczego ktoś zgodził się z odpowiedzią Ejrowleya? Wciąż szukam najlepszego możliwego rozwiązania i udzielę kredytu tam, gdzie należy się kredyt. Ale to szwy jak realne rozwiązanie, nie? – Frankie

+0

mimo że twój system nie jest dokładnie tym, na co idę; Wierzę, że schemat tabeli "Media Wiki" w Edwardzie Williamsie byłby bliższą odpowiedzią zarówno pod względem wydajności, jak i dostępności; Wierzę, że jesteś odpowiedzią na odpowiedź Edwardsa z lepszymi schematami, więc akceptuję to. Dzięki! – Frankie

6

Wystarczy popatrzeć na to pytanie: How to version control a record in a database

dlaczego nie ma oddzielnego history_table dla każdej tabeli (zgodnie z przyjętą odpowiedzi na pytanie) połączonego? To po prostu ma złożony klucz podstawowy w oryginalnych tabelach PK i numer wersji. Nadal będziesz musiał przechowywać dane gdzieś.

+0

Twoja odpowiedź jest bardzo interesująca. Specjalnie zaprojektowany schemat bazy danych 'Media Wiki'. Tworzy dodatkową warstwę 'table -> keys revers -> revisions data' utrzymując' tabelę danych' tak małą, jak to tylko możliwe, jednocześnie dostarczając historię zmian i będąc w stanie nawigować pomiędzy wersjami tam iz powrotem, jak to robi SO. Nadal zastanawiam się, czy istnieje bardziej elegancki sposób przechowywania. – Frankie

1

Dla jednego z naszych projektów wybraliśmy następujący sposób:

Entries Table 
+----+-----------+---------+ 
| id | date_from | date_to | 
+----+--------_--+---------+ 

EntryProperties Table 
+----------+-----------+-------+------+--------+--------+ 
| entry_id | date_from | title | text | index1 | index2 | 
+----------+-----------+-------+------+--------+--------+ 

Dość dużo skomplikowane, nadal pozwala śledzić pełny cykl życia obiektu. Więc dla zapytań podmioty aktywne jechaliśmy do:

SELECT 
entry_id, title, text, index1, index2 
FROM 
Entities INNER JOIN EntityProperties 
ON Entities.id = EntityProperties.entity_id 
AND Entities.date_to IS NULL 
AND EntityProperties.date_to IS NULL 

Jedynym problemem było dla sytuacji jednostka jest usuwany (tak kładziemy date_to tam), a następnie przywrócony przez admin.Używając danego schematu, nie ma sposobu na śledzenie tego rodzaju sztuczek.

Ogólną wadą każdej takiej próby jest oczywistość - musisz napisać tony TSQL, gdzie nie-wersjonowane DB-e będą działać dla czegoś takiego jak wybierz A dołącz B.

Powiązane problemy