Někdy může být důležité evidovat, kdo, kdy, z čeho a na co mění data v databázi. Na škole jsem měl referát o temporálních databázích, které si samy od sebe uchovávají historická data a umožňují s nimi snadno pracovat, takže je možné podívat se např. na přesný otisk dat z nějakého okamžiku v minulosti, běžně rozšířené databáze tuto vlastnost ale nemají.
Pokud se záznamem provedených operací nepotřebujeme intenzivně pracovat a stačí ho mít někde uložený pro případ, že by bylo potřeba výjimečně něco dohledat, nabízí ideální úložiště binární log MySQL. Do toho se zaznamenávají veškeré změny v databázi (nikoliv tedy požadavky na získání dat). Pokud si uložíme otisk databáze a pustíme binární logování, tak v okamžiku, kdy bude potřeba ověřit nějakou změnu, stačí se podívat do tohoto logu. Pokud bychom potřebovali znát předchozí hodnotu, je možné databázi obnovit z otisku a log spustit až do okamžiku zkoumané změny. Pokud bychom potřebovali uchovávat informaci o tom, kdo danou změnu provedl případně další doplňující informace, je možné je připojit v SQL komentáři k dotazu, čímž se do binárního logu také uloží.
Pokud má být záznam provedených operací dostupný běžným uživatelům bez přístupu k binárnímu logu, je možné ho ukládat do běžné databázové tabulky. Na aplikační úrovni to lze zajistit např. takovouto funkcí:
<?php function mysql_insert($table, $set) { $return = mysql_query("INSERT INTO $table (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")"); if ($return) { $id = mysql_insert_id(); foreach ($set as $key => $val) { mysql_query("INSERT INTO log (tabulka, tabulka_id, sloupec, nova, provedeno, id_admin) VALUES ('$table', '$id', '$key', $val, NOW(), '$_SESSION[LOGIN_ID]')"); } } return $return; } ?>
Funkce předpokládá, že v modifikované tabulce bude existovat sloupec AUTO_INCREMENT, v tabulce log
tento sloupec naopak být nesmí, protože příští volání mysql_insert_id by vrátilo klíč z tabulky log
. Dotazy pro UPDATE a DELETE by vypadaly podobně, s tím rozdílem, že do sloupce stara
by se ukládala předchozí hodnota sloupce.
Na tomto místě je vhodné upozornit na MySQL tabulku typu ARCHIVE, která se pro ukládání záznamu operací ideálně hodí – data jsou při ukládání automaticky komprimována, ukládání probíhá ve větších blocích, takže tolik nezdržuje a nejsou umožněny operace UPDATE a DELETE, takže záznamy nelze tak snadno falšovat. Získání dat je pochopitelně pomalé, především proto, že nelze používat indexy.
Řešení na aplikační úrovni má samozřejmě tu nevýhodu, že pokud někdo změnu udělá přímo v databázi, do historie operací se neprojeví. Databáze by samozřejmě měla být zabezpečena tak, aby s ní přímo mohly pracovat jen oprávněné osoby, ale i ty je někdy potřeba kontrolovat. Řešením by bylo místo PHP funkce vytvořit trigger, který by změny automaticky ukládal. Ale vytvořit ho tak, aby automaticky sledoval třeba i nově přidané sloupce do tabulek, by dalo dost práce.
Diskuse je zrušena z důvodu spamu.