Zawartość pliku dziennika transakcji bardziej szczegółowo

11

Mam pytanie dotyczące zawartości dziennika transakcji (w skrócie nazwijmy go LDF). Zakładam bazę danych z pełnym modelem odzyskiwania.

Przeczytałem, że plik LDF zawiera (logi) każdą operację w bazie danych (czyli w trybie pełnego odzyskiwania). Czym różni się od logowania podczas BEGIN TRAN; COMMAND(s); COMMIT? Pytam, ponieważ najwyraźniej możesz wycofać transakcje, ale nie możesz wycofać standardowych poleceń (w trybie pełnego odzyskiwania).

Wydaje mi się, że podczas transakcji zawartość logowana do pliku LDF jest inna niż w przypadku zwykłego pełnego odzyskiwania danych. Czy to prawda? Czym się różni? Czy to tylko włączenie operacji „cofnij” dla każdego działania?

W powiązanej notatce słyszałem, że istnieją komercyjne narzędzia do „wycofywania / cofania” standardowych zapytań przy użyciu pełnego pliku odzyskiwania LDF. Jak oni to robią? Czy analizują zawartość LDF i próbują wymyślić operacje odwrotne / cofanie?

Nigdy nie przestawaj się uczyć
źródło
Powiązane: Jak przeglądać dzienniki transakcji w SQL Server 2008 na przepełnieniu stosu.
Vadzim

Odpowiedzi:

11

Różnica polega na tym, że to, co nazywasz „standardowymi poleceniami”, zawiera transakcje niejawne (jak w przypadku „transakcji niejawnych” i nie rzeczywistych transakcji niejawnych, które oznaczają coś innego ), więc za każdym razem, gdy INSERTwydasz polecenie bez wyraźnej transakcji, otworzy transakcję, wstaw dane i automatycznie zatwierdź. Nazywa się to transakcją automatycznego zatwierdzania.

Dlatego też nie możesz tego cofnąć INSERT: jest już popełnione. Zasada jest więc taka sama, jak w przypadku transakcji jawnych: nie można wycofać, gdy zostaną one zatwierdzone .

Możesz zobaczyć, co mam na myśli bezpośrednio z SQL Server.

Microsoft dostarcza SQL Serverowi o nazwie DMF, sys.fn_dblogktórej można użyć do przeglądania dziennika transakcji danej bazy danych.

Do tego prostego eksperymentu użyję bazy danych AdventureWorks:

USE AdventureWorks2008;
GO

SELECT TOP 10 *
FROM dbo.Person;
GO

INSERT INTO dbo.Person (FirstName, MiddleName, LastName, Gender, Date)
VALUES ('Never', 'Stop', 'Learning', 'M', GETDATE());
COMMIT;

BEGIN TRAN;
INSERT INTO dbo.Person (FirstName, MiddleName, LastName, Gender, Date)
VALUES ('Never', 'Stop', 'Learning', 'M', GETDATE());
COMMIT;
GO

SELECT *
FROM sys.fn_dblog(NULL, NULL);
GO

Tutaj robię dwie wstawki: jedną z wyraźną transakcją i drugą.

W pliku dziennika widać, że absolutnie nie ma między nimi żadnej różnicy:

Automatyczne zatwierdzanie kontra jawne transakcje

Czerwona to INSERTtransakcja z automatycznym zatwierdzeniem, a niebieska INSERTz jawną transakcją.

Jeśli chodzi o wspomniane narzędzia innych firm, tak, analizują one dziennik bazy danych i generują normalny kod T-SQL w celu „cofnięcia” lub „powtórzenia” operacji. Mam na myśli, że nie robią nic specjalnego poza generowaniem skryptu, który spowoduje dokładnie odwrotność tego, co jest w pliku dziennika.

ivanmp
źródło
7

Wyjaśnię, jak działają narzędzia komercyjne, na przykładzie dziennika ApexSQL

I na powiązaną notatkę słyszałem, że istnieją komercyjne narzędzia do „przywracania / cofania” standardowych zapytań przy użyciu pełnego pliku odzyskiwania LDF. Jak oni to robią? Czy analizują zawartość LDF i próbują wymyślić operacje odwrotne / cofanie?

Tak, czytają plik LDF (online lub odłączony) i pliki trn (kopie zapasowe dziennika transakcji), sprawdzają, co się stało, i tworzą skrypt, który zrobi to samo lub odwrotnie.

Zauważ jednak, że skrypt cofania i ponawiania nie musi być dokładnie taki sam jak wykonywany, ale efekt będzie dokładnie taki sam.

Na przykład, jeśli wykonanym skryptem było:

DELETE FROM [Person].[AddressType] WHERE Name  = 'New Loc22'

Dziennik transakcji zarejestruje, że wiersz w tabeli z wartościami kolumn 9, „Nowy Loc22”, „41BC2FF6-F0FC-475F-8EB9-CEC1805AA0F6” i „2002/06/01 00: 00: 00.000” został usunięty. Ze struktury tabeli narzędzie odczyta, że ​​klucz podstawowy to kolumna AddressType i utworzy następujący skrypt przywracania:

DELETE FROM [Person].[AddressType] WHERE [AddressTypeID] = 9

Należy pamiętać, że transakcja jest powiązana z kolumną Klucz podstawowy, a nie z kolumną użytą w oryginalnej klauzuli where. Podobnie skryptem cofania będzie:

INSERT INTO [Person].[AddressType] ([AddressTypeID], [Name], [rowguid], [ModifiedDate]) VALUES (9, N'New loc22' COLLATE SQL_Latin1_General_CP1_CI_AS, '41bc2ff6-f0fc-475f-8eb9-cec1805aa0f6', '20020601 00:00:00.000')

wprowadź opis zdjęcia tutaj

Uwaga: Pracuję dla ApexSQL jako inżynier wsparcia

Milena Petrovic
źródło