wtorek, 25 października 2011

ATTACH_FORCE_REBUILD_LOG

W wielu systemach bazodanowych plik loga (LDF) znajduje sie na oddzielnych dyskach niż pliki danych (MDF, NDF).
Co zrobić jeśli w przypadku awarii utracimy plik LDF (np.: awaria sprzetowa dysków)? Odpowiedź jest prosta - przywracamy backup.

Co w przypadku gdy jednak chcemy odzyskać dane z pliku MDF?
W sieci można znaleźć wiele dziwnych opisów odzyskiwania pliku MDF po stracie LDF, większość z nich pochodzi jeszcze z czasów SQL Server 2000.

Od wersji SQL Server 2005 istnieje nieudokumentowany parametr do polecenia 'CREATE DATABASE' umożliwiający podpięcie samej bazy danych bez pliku LDF.

Przykład:
Tworzymy nową bazę danych :
CREATE DATABASE [Demo] ON  PRIMARY 
( NAME = N'Demo', FILENAME = N'C:\Temp\Demo.mdf')
 LOG ON 
( NAME = N'Demo_log', FILENAME = N'C:\Temp\Demo_log.ldf')
GO

USE [Demo]
GO

CREATE TABLE Items(Id INT IDENTITY(1,1) PRIMARY KEY, Name VARCHAR(20), Price MONEY)
GO

INSERT INTO Items VALUES ('CAR', 100000);
INSERT INTO Items VALUES ('PARTS', 2000);
GO
Rozpoczynamy transakcję modyfikującą dane:
BEGIN TRAN;
UPDATE Items SET Price = 0 WHERE Name = 'PARTS'
GO

CHECKPOINT;
GO
Na innej konsoli zatrzymujemy serwer bazodanowy:
SHUTDOWN WITH NOWAIT;
GO
Po zatrzymaniu serwera SQL usuwamy plik LDF (w naszym przypadku 'C:\Temp\Demo_log.ldf') i startujemy serwer SQL ponownie.
Po zalogowaniu się do serwera sprawdzamy status bazy danych:
SELECT DATABASEPROPERTYEX ('Demo', 'STATUS') AS 'Status';
Jest SUSPECT, czyli zgodnie z oczekiwaniami. Teraz odłączamy baze danych.
ALTER DATABASE Demo SET OFFLINE
GO
EXEC sp_detach_db 'Demo';
GO
i próbujemy podpiąć ją standardowymi komendami:
CREATE DATABASE DemoFix ON
   (NAME = DemoSuspect, FILENAME = N'C:\Temp\Demo.mdf')
FOR ATTACH_REBUILD_LOG;
GO
File activation failure. The physical file name "C:\Temp\Demo_log.ldf" may be incorrect. The log cannot be rebuilt because there were open transactions/users when the database was shutdown, no checkpoint occurred to the database, or the database was read-only. This error could occur if the transaction log file was manually deleted or lost due to a hardware or environment failure. 
Msg 1813, Level 16, State 2, Line 1 Could not open new database 'DemoFix'. CREATE DATABASE is aborted.

Spróbujmy zatem naszego nowego polecenia:
CREATE DATABASE DemoFix ON
   (NAME = DemoSuspect, FILENAME = N'C:\Temp\Demo.mdf')
FOR ATTACH_FORCE_REBUILD_LOG;
GO
File activation failure. The physical file name "C:\Temp\Demo_log.ldf" may be incorrect.
New log file 'C:\Temp\DemoFix_log.LDF' was created.


Baza działa! Ale niestety nie jest tak pięknie. Stworzona baza danych nie jest spójna. Zobaczmy co znajduje się w naszej tabeli w nowej bazie:
SELECT * FROM [DemoFix].[dbo].[Items]

Jak widać w tabeli zapisane są modyfikacje transakcji która się nie zakończyła.