Database
 sql >> Baza danych >  >> RDS >> Database

Mit, że DROP i OBCIĄŻ TABELĘ nie są rejestrowane

W świecie SQL Server istnieje uporczywy mit, że zarówno DROP TABLE i TRUNCATE TABLE polecenia nie są rejestrowane.

Oni nie są. Oba są w pełni rejestrowane, ale skutecznie rejestrowane.

Możesz łatwo to sobie udowodnić. Uruchom następujący kod, aby skonfigurować testową bazę danych i tabelę, i pokaż, że w naszej tabeli mamy 10 000 wierszy:

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

Wyniki:

Liczba wierszy
———–
10000

A potem następujący kod, który obcina tabelę w transakcji i sprawdza liczbę wierszy:

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

Wyniki:

Liczba wierszy
———–
0

Teraz stół jest pusty. Ale mogę wycofać transakcję i przywrócić wszystkie dane:

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

Wyniki:

Liczba wierszy
———–
10000

Wyraźnie TRUNCATE operacja musi być zarejestrowana, w przeciwnym razie operacja wycofania nie zadziała.

Skąd więc bierze się błędne przekonanie?

Pochodzi z zachowania DROP i TRUNCATE operacje na dużych stołach. Zakończą się niemal natychmiast, a jeśli zajrzysz do dziennika transakcji za pomocą fn_dblog zaraz potem zobaczysz tylko niewielką liczbę rekordów dziennika wygenerowanych z operacji. Ta mała liczba nie koreluje z rozmiarem obcinanej lub usuwanej tabeli, więc wygląda na to, że DROP i TRUNCATE operacje nie są rejestrowane.

Ale są w pełni zalogowane, jak pokazałem powyżej. Więc gdzie są zapisy dziennika dotyczące operacji?

Odpowiedź jest taka, że ​​rekordy dziennika zostaną utworzone, ale nie natychmiast, przez mechanizm zwany „odroczonym upuszczaniem”, który został dodany w dodatku SQL Server 2000 SP3.

Gdy tabela zostanie usunięta lub obcięta, wszystkie strony pliku danych przydzielone do tabeli muszą zostać cofnięte. Mechanizm tego działania przed SQL Server 2000 SP3 był następujący:

Dla każdego ekstentu przydzielonego do tabeli

Rozpocznij

Uzyskaj wyłączną blokadę alokacji dla ekstentu



Sonda blokada strony dla każdej strony w zakresie (uzyskaj blokadę w trybie wyłączności i natychmiast ją usuń, upewniając się, że nikt inny nie ma zablokowanej strony)



NIE zwolnić blokadę zasięgu, gwarantującą, że nikt inny nie będzie mógł jej użyć



Przejdź do następnego zakresu

Koniec

Ponieważ wszystkie blokady zakresu były utrzymywane do końca operacji, a każda blokada zajmuje niewielką ilość pamięci, możliwe było, że menedżer blokad zabraknie pamięci, gdy DROP lub TRUNCATE bardzo dużego stołu. Niektórzy klienci korzystający z SQL Server zaczęli odkrywać, że napotykają problemy z brakiem pamięci w SQL Server 2000, ponieważ tabele rozrastały się do bardzo dużych rozmiarów i znacznie przewyższały wzrost pamięci systemowej.

Mechanizm odroczonego upuszczania symuluje DROP lub TRUNCATE operacja zostaje zakończona natychmiast, poprzez odczepienie alokacji dla tabeli i umieszczenie ich w „kolejce z odroczonym upuszczaniem”, w celu późniejszego przetworzenia przez zadanie w tle. Ta operacja odczepiania i przesyłania generuje tylko kilka rekordów dziennika. Jest to operacja, która jest wykonywana i wycofywana w powyższym przykładzie kodu.
„Zadanie odroczonego opuszczania w tle” obraca się co kilka sekund i cofa wszystkie strony i ekstenty w kolejce odroczonego opuszczania w małym wsady, gwarantując, że operacji nie zabraknie pamięci. Wszystkie te dezalokacje są w pełni rejestrowane, ale pamiętaj, że cofnięcie alokacji strony pełnej rekordów danych lub indeksu nie powoduje rejestrowania pojedynczych usunięć tych rekordów; zamiast tego cała strona jest po prostu oznaczona jako cofnięta alokacja w odpowiedniej mapie bajtowej alokacji PFS (Page Free Space).

Począwszy od SQL Server 2000 SP3, po wykonaniu DROP lub TRUNCATE tabeli, zobaczysz tylko kilka generowanych rekordów dziennika. Jeśli poczekasz około minuty, a następnie ponownie zajrzysz do dziennika transakcji, zobaczysz tysiące rekordów dziennika wygenerowanych przez operację odroczonego upuszczania, z których każdy zwalnia stronę lub zakres. Operacja jest w pełni i wydajnie rejestrowana.

Oto przykład, wykorzystując scenariusz, który stworzyliśmy powyżej:

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

Wyniki:

LogRecCount

———–

25

Jak widać, wyraźnie nie ma rekordów logów zwalniających alokację 10 000 stron plus 1250 ekstentów w tabeli TestTable.

Jeśli poczekam kilka sekund, a następnie uruchomię fn_dblog kod ponownie, otrzymuję:

LogRecCount

———–

3811

Możesz się zastanawiać, dlaczego nie ma co najmniej 10 000 rekordów dziennika – po jednym dla każdej strony, która jest zwalniana. Dzieje się tak, ponieważ cofanie alokacji stron jest nawet wydajnie rejestrowane – z jednym rekordem dziennika odzwierciedlającym zmiany alokacji stron PFS dla 8 kolejnych stron pliku danych, zamiast jednego rekordu dziennika dla każdej strony pliku danych, odzwierciedlającego zmianę statusu alokacji na stronie PFS.

SQL Server zawsze stara się generować jak najmniej dzienników transakcji, przy jednoczesnym przestrzeganiu zasad dotyczących pełnego lub minimalnego rejestrowania w oparciu o bieżący model odzyskiwania. Jeśli chcesz przejrzeć rzeczywiste rekordy dziennika generowane przez mechanizmy unhook-and-transfer i deferred-drop, po prostu zamień * na COUNT (*) w powyższym kodzie fn_dblog i poszukaj transakcji z nazwą transakcji ustawioną na DeferredAllocUnitDrop::Process .

W przyszłych postach omówię elementy wewnętrzne, które leżą u podstaw innych uporczywych mitów dotyczących aspektów wydajności SQL Server Storage Engine.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak zainstalować SQLcl w systemie Windows?

  2. Adaptacyjny próg łączenia

  3. W poszukiwaniu szybkiej pamięci lokalnej

  4. Patrząc na wydajność migawki bazy danych

  5. Model bazy danych dla usługi taksówkowej