sql >> Databáze >  >> RDS >> Database

Mýtus, že DROP a TRUNCATE TABLE nejsou protokolované

Ve světě SQL Serveru existuje trvalý mýtus, že obě DROP TABLE a TRUNCATE TABLE příkazy nejsou protokolovány.

Oni nejsou. Oba jsou plně protokolované, ale efektivně protokolované.

Můžete to snadno dokázat sami. Spusťte následující kód pro nastavení testovací databáze a tabulky a ukažte, že v naší tabulce máme 10 000 řádků:

CREATE DATABASE [TruncateTest];
GO
 
ALTER DATABASE [TruncateTest] SET RECOVERY SIMPLE;
GO
 
USE [TruncateTest];
GO
 
CREATE TABLE [TestTable] (
    [c1]    INT IDENTITY,
    [c2]    CHAR (8000) DEFAULT 'a');
GO
 
SET NOCOUNT ON;
GO
 
INSERT INTO [TestTable] DEFAULT VALUES;
GO 10000
 
SELECT
    COUNT (*) AS N'RowCount'
FROM
    [TestTable];
GO

Výsledky:

Počet řádků
———–
10 000

A pak následující kód, který zkrátí tabulku v transakci a zkontroluje počet řádků:

BEGIN TRAN;
GO
TRUNCATE TABLE [TestTable];
GO
 
SELECT
    COUNT (*) AS N'RowCount'
FROM
    [TestTable];
GO

Výsledky:

Počet řádků
———–
0

Nyní je stůl prázdný. Mohu však transakci vrátit zpět a vrátit všechna data zpět:

ROLLBACK TRAN;
GO
 
SELECT
    COUNT (*) AS N'RowCount'
FROM
    [TestTable];
GO

Výsledky:

Počet řádků
———–
10 000

Jasně TRUNCATE operace musí být zaprotokolována, jinak by operace vrácení zpět nefungovala.

Odkud tedy pochází mylná představa?

Vychází z chování DROP a TRUNCATE operace na velkých stolech. Dokončí se téměř okamžitě, a pokud se podíváte do protokolu transakcí pomocí fn_dblog hned poté uvidíte pouze malý počet záznamů protokolu vygenerovaných z operace. Toto malé číslo nekoreluje s velikostí tabulky, která je zkrácena nebo vynechána, takže to vypadá, jako by DROP a TRUNCATE operace nejsou protokolovány.

Ale jsou plně přihlášeni, jak jsem ukázal výše. Kde jsou tedy záznamy protokolu operací?

Odpověď zní, že záznamy protokolu budou vytvořeny, ale ne okamžitě, pomocí mechanismu zvaného „odložený pokles“, který byl přidán do SQL Server 2000 SP3.

Když je tabulka zrušena nebo zkrácena, musí být uvolněny všechny stránky datového souboru přidělené pro tabulku. Mechanismus tohoto před SQL Server 2000 SP3 byl následující:

Pro každý rozsah přidělený tabulce

Začátek

Získejte eXkluzivní alokační zámek pro daný rozsah



Vyzkoušejte uzamčení stránky pro každou stránku v rozsahu (získejte zámek v eXclusive režimu a okamžitě jej zahoďte, ujistěte se, že nikdo jiný nemá stránku zamčenou)



NE uvolněte zámek rozsahu a zaručíte, že nikdo jiný nebude moci tento rozsah použít



Přesunout na další rozsah

Konec

Protože všechny zámky rozsahu byly drženy až do konce operace a každý zámek zabírá malé množství paměti, mohlo se stát, že správci zámků dojde paměť, když DROP nebo TRUNCATE došlo k velmi velké tabulce. Někteří zákazníci SQL Serveru začali zjišťovat, že na SQL Server 2000 narazili na nedostatek paměti, protože tabulky se velmi rozrostly a výrazně předstihly nárůst systémové paměti.

Mechanismus odloženého pádu simuluje DROP nebo TRUNCATE operace se dokončí okamžitě, odpojením alokací pro tabulku a jejich umístěním do „fronty odloženého odložení“ pro pozdější zpracování úlohou na pozadí. Tato operace odpojení a přenosu generuje pouze několik záznamů protokolu. Toto je operace, která se provádí a je vrácena zpět v mém příkladu kódu výše.
Úloha „odloženého zapuštění na pozadí“ se otočí každých několik sekund a uvolní všechny stránky a rozsahy ve frontě odloženého zahození po malých dávky, zaručující, že operace nebude mít nedostatek paměti. Všechna tato dealokace jsou plně protokolovaná, ale pamatujte, že uvolnění stránky plné dat nebo indexových záznamů nezaznamenává jednotlivá odstranění těchto záznamů; místo toho je celá stránka označena jako uvolněná v příslušné bajtové mapě přidělení PFS (Page Free Space).

Od SQL Server 2000 SP3 dále, když provedete DROP nebo TRUNCATE tabulky, uvidíte pouze několik generovaných záznamů protokolu. Pokud asi minutu počkáte a pak se znovu podíváte do protokolu transakcí, uvidíte, že operací odloženého odložení byly vygenerovány tisíce záznamů protokolu, z nichž každý uvolňuje stránku nebo rozsah. Operace je plně a efektivně protokolována.

Zde je příklad pomocí scénáře, který jsme vytvořili výše:

CHECKPOINT;
GO
TRUNCATE TABLE [TestTable];
GO
SELECT
    COUNT (*) AS N'LogRecCount'
FROM
    fn_dblog (NULL, NULL);
GO

Výsledky:

LogRecCount

———–

25

Jak vidíte, v tabulce TestTable zjevně neexistují žádné záznamy protokolu, které by uvolnily 10 000 stránek plus 1 250 oblastí.

Pokud počkám několik sekund a poté spustím fn_dblog kód znovu, dostanu:

LogRecCount

———–

3811

Možná se divíte, proč neexistuje alespoň 10 000 záznamů protokolu – jeden pro každou uvolněnou stránku. Je to proto, že dealokace stránek jsou dokonce efektivně protokolovány – s jedním záznamem protokolu odrážejícím změny alokace stránky PFS pro 8 po sobě jdoucích stránek datového souboru, namísto jednoho záznamu protokolu pro každou stránku datového souboru odrážejícího její stav alokace, který se mění na stránce PFS.

SQL Server se vždy snaží vytvořit co nejmenší protokol transakcí a přitom stále dodržovat pravidla o úplném nebo minimálním protokolování na základě aktuálního modelu obnovy. Pokud se chcete podívat na skutečné záznamy protokolu generované mechanismy unhook-and-transfer a odloženého zahození, jednoduše nahraďte * za COUNT (*) v kódu fn_dblog výše a vyhledejte transakci s názvem transakce nastaveným na DeferredAllocUnitDrop::Process .

V budoucích příspěvcích se budu zabývat vnitřními prvky, které jsou základem dalších přetrvávajících mýtů o výkonnostních aspektech SQL Server Storage Engine.


  1. Jak provést UPDATE Pass-Through Query v SQL Server

  2. SET DATEFIRST – Nastavte první den v týdnu na SQL Serveru

  3. Oracle:Dny mezi dvěma daty a Vyloučit pracovní dny, jak zacházet se zápornými čísly

  4. Příklad funkce Oracle (vrácené číslo)