I'm going to start an explicit user transaction and update a row in the table:
BEGIN
TRANSACTION;
GO
UPDATE
salaries SET Salary = 0 WHERE LastName='Brown';
GO
Now I'm going to force the data page holding the updated row to be written to disk:
CHECKPOINT
;
GO
So we have an active, uncommitted transaction that's modified the table, and the table modification has been written to disk. If the power failed at this point, crash recovery would run and the transaction would be rolled back. I'm going to simulate this by shutting down SQL Server. In another connection:
SHUTDOWN
WITH NOWAIT;
GO
Server shut down by NOWAIT request from login ROADRUNNERPR\paul.
SQL Server is terminating this process.
I'm also going to simulate damage to the transaction log:
C:\Documents and Settings\paul>del "C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\emergencydemo_log.LDF"
C:\Documents and Settings\paul>
Now when I start up SQL Server again, we see the following in the error log:
2007-10-02 11:39:47.14 spid18s Starting up database 'emergencydemo'.
2007-10-02 11:39:47.46 spid18s Error: 17207, Severity: 16, State: 1.
2007-10-02 11:39:47.46 spid18s FileMgr::StartLogFiles: Operating system error 2(The system cannot find the file specified.) occurred while creating or opening file 'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\emergencydemo_log.LDF'. Diagnose and correct the operating system error, and retry the operation.
2007-10-02 11:39:47.60 spid18s File activation failure. The physical file name "C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\emergencydemo_log.LDF" may be incorrect.
2007-10-02 11:39:47.60 spid18s The log cannot be rebuilt because the database was not cleanly shut down.
The database wasn't cleanly shut down and the transaction log isn't available so recovery couldn't run. The final message is interesting - there's a feature in SQL Server 2005 that if you attach or startup a database without a transaction log file, and the database was cleanly shut down, SQL Server will create a new log file automatically. In our case that can't happen though.
What happens if I try to get into the database?
USE
emergencydemo;
GO
Msg 945, Level 14, State 2, Line 1
Database 'emergencydemo' cannot be opened due to inaccessible files or insufficient memory or disk space. See the SQL Server errorlog for details.
So what state is the database in?
SELECT
DATABASEPROPERTYEX ('emergencydemo', 'STATUS');
GO
returns SUSPECT. But checking the sys.databases table
SELECT
state_desc FROM sys.databases WHERE name='emergencydemo';
GO
returns RECOVERY PENDING. This is what I'd expect, as recovery didn't get a chance to even start.
Now I'll set the database into EMERGENCY mode so I can get in and see what state things are in:
ALTER
DATABASE emergencydemo SET EMERGENCY;
GO
In the errorlog you can tell when a database has been put into EMERGENCY mode:
2007-10-02 11:53:52.57 spid51 Setting database option EMERGENCY to ON for database emergencydemo.
2007-10-02 11:53:52.59 spid51 Starting up database 'emergencydemo'.
2007-10-02 11:53:52.62 spid51 The database 'emergencydemo' is marked EMERGENCY_MODE and is in a state that does not allow recovery to be run.
Let's try that again:
USE
emergencydemo;
GO
This time it works. What's the state of the data?
SELECT
* FROM salaries;
GO
FirstName LastName Salary
-------------------- -------------------- -----------
John Williamson 10000
Stephen Brown 0
Jack Bauer 10000
It's inconsistent, as I'd expect.
That's the catch with EMERGENCY mode - you can get into the database but recovery hasn't run or completed so you don't know whether the database is logically or structurally consistent. However, at least you can get into the database to extract data out or repair any damage.
In the next post (later today) I'll show you how to repair any damage using the emergency-mode repair feature of DBCC CHECKDB.