sql >> Databáze >  >> RDS >> Mysql

Uložte všechny změny dat se všemi detaily (jako Stackoverflow)

Už o tom nějakou dobu přemýšlím a napadají mě jen dva způsoby, jak to udělat. Oba mohou fungovat plně transparentně, když jsou vytvořeny do abstraktní datové vrstvy / modelu.

Mimochodem, v doktríně mapovače ORM existuje implementace pro "verzovatelná" tabulková data. Podívejte se na tento příklad v jejich dokumentech . Možná to vyhovuje vašim potřebám, ale nevyhovuje mým. Zdá se, že po smazání původního záznamu smaže všechna data historie, takže není skutečně bezpečný pro revize.

Možnost A:mít kopii každé tabulky pro uložení dat revizí

Řekněme, že máte jednoduchou tabulku kontaktů:

CREATE TABLE contact (
    id INT NOT NULL auto_increment,
    name VARCHAR(255),
    firstname VARCHAR(255),
    lastname VARCHAR(255),
    PRIMARY KEY (id)
)

Vytvořili byste kopii této tabulky a přidali data revize:

CREATE TABLE contact_revisions (
    id INT NOT NULL,
    name VARCHAR(255),
    firstname VARCHAR(255),
    lastname VARCHAR(255),
    revision_id INT auto_increment,
    type ENUM('INSERT', 'UPDATE', 'DELETE') NOT NULL,
    change_time DEFAULT current_timestamp,
    PRIMARY KEY(revision_id)
)

Sledujte INSERT a UPDATE pomocí AFTER spouštěče. Na každou novou revizi dat v originálu vložte kopii nových dat do tabulky revizí a nastavte úpravu type správně.

Pro přihlášení DELETE revizně bezpečné, musíte také vložit nový řádek do tabulky historie! K tomu byste měli použít BEFORE DELETE spustit a uložit nejnovější hodnoty před jejich odstraněním. Jinak budete muset odstranit všechny NOT NULL omezení také v tabulce historie.

Některé důležité poznámky týkající se této implementace

  • Pro tabulku historie musíte zrušit každý UNIQUE KEY (zde:PRIMARY KEY ) z tabulky revizí, protože budete mít stejný klíč několikrát pro každou revizi dat.
  • Když ALTER schéma a data v původní tabulce prostřednictvím aktualizace (např. aktualizace softwaru), musíte zajistit, aby stejná data nebo opravy schématu byly aplikovány i na tabulku historie a její data. Jinak se při návratu ke starší revizi sady záznamů dostanete do problémů.
  • Ve skutečné implementaci byste chtěli vědět, který uživatel upravil data. Aby bylo toto revizní bezpečné, neměl by být uživatelský záznam nikdy odstraněn z tabulky uživatelů. Měli byste pouze deaktivovat účet pomocí příznaku.
  • Jedna uživatelská akce obvykle zahrnuje více než jednu tabulku. V reálné implementaci byste také museli sledovat, které změny ve více tabulkách patří k jedné uživatelské transakci a také v jakém pořadí. Ve skutečném případě použití byste chtěli vrátit všechny změny jedné transakce dohromady v obráceném pořadí. To by vyžadovalo další tabulku revizí, která sleduje uživatele a transakce a udržuje volný vztah ke všem těmto jednotlivým revizím v tabulkách historie.

Výhody:

  • zcela v databázi, nezávisle na kódu aplikace. (No, ne, když je důležité sledování uživatelských transakcí. To by vyžadovalo určitou logiku mimo rozsah jediného dotazu)
  • všechna data jsou v původním formátu, žádné implicitní konverze typu.
  • dobrý výkon při vyhledávání v revizích
  • snadné vrácení zpět. Stačí provést jednoduchý INSERT .. ON DUPLICATE KEY UPDATE .. příkaz na původní tabulku s použitím dat z revize, kterou chcete vrátit.

Přednosti:

  • Těžko se ručně implementuje.
  • Těžké (ale ne nemožné) automatizovat, pokud jde o migrace databází / aktualizace aplikací.

Jak již bylo uvedeno výše, doktríny versionable dělá něco podobného.

Možnost B:mít centrální tabulku protokolu změn

předmluva:špatný postup, zobrazený pouze pro ilustraci alternativy.

Tento přístup silně spoléhá na aplikační logiku, která by měla být skryta v datové vrstvě/modelu.

Máte centrální tabulku historie, která sleduje

  • Kdo to udělal
  • kdy
  • upravit, vložit nebo odstranit
  • jaká data
  • ve kterém poli
  • z které tabulky

Stejně jako v jiném přístupu můžete také chtít sledovat, které jednotlivé změny dat patří k jedné akci / transakci uživatele a v jakém pořadí.

Výhody:

  • při přidávání polí do tabulky nebo vytváření nové tabulky není třeba udržovat synchronizaci s původní tabulkou. měří se transparentně.

Přednosti:

  • špatný postup při používání jednoduché hodnoty =úložiště klíčů v databázi
  • špatný výkon vyhledávání kvůli implicitním typům konverzí
  • může zpomalit celkový výkon aplikace/databáze, když se centrální tabulka historie stane úzkým hrdlem kvůli zámkům zápisu (toto platí pouze pro konkrétní stroje se zámky tabulek, např. MyISAM)
  • Implementace vrácení zpět je mnohem těžší
  • možné chyby převodu dat / ztráta přesnosti v důsledku převodu implicitního typu
  • nesleduje změny, když přímo přistupujete k databázi někde ve vašem kódu namísto použití vaší modelové / datové vrstvy a zapomeňte, že v tomto případě musíte do protokolu revizí zapisovat ručně. Může to být velký problém při práci v týmu s jinými programátory.

Závěr:

  • Možnost B může být velmi užitečné pro malé aplikace jako jednoduché "vhození", když je to jen pro protokolování změn.
  • Pokud se chcete vrátit v čase a mít možnost snadno porovnat rozdíly mezi historickými revizemi 123 na revizi 125 a/nebo se vrátit ke starým datům a poté Možnost A je obtížná cesta.


  1. dotaz na tabulku každou sekundu pro upozornění. Je to dobrá praxe?

  2. Vložení více řádků do Oracle

  3. Mohu provést výběr, aktualizaci a odstranění mysql v jednom dotazu?

  4. Jak formátovat datum a čas na serveru SQL Server