Bruno Perroni
DBA SQL Server com mais de 6 anos de experiência!

Bancos de Dados em Suspect

Eis que um belo dia você está trabalhando tranquilamente e sem mais nem menos o servidor reinicia sozinho, seja por um patch mal planejado ou por uma falha de hardware, passado o susto e com o servidor online novamente, você começa a checar se está tudo em ordem e percebe que um banco de dados está no modo Suspect.

E você também se dá conta de que a base em questão não tem rotina de backup de log.

E agora? o que fazer . . .

Nesse post vou demonstrar como proceder em caso de um banco de dados ficar no modo Suspect.

Primeiramente vamos causar um evento que deixará o banco de dados no modo Suspect.

Para isso siga os passos abaixo:

Crie um banco de dados qualquer, nesse exemplo terá o nome de SUSPECT.

CREATE DATABASE SUSPECT

Crie uma tabela qualquer e adicione alguns registros.

CREATE TABLE [dbo].[PESSOA](
	[id] [int] NULL,
	[nome] [varchar](100) NULL
) ON [PRIMARY]

INSERT INTO PESSOA VALUES (1, 'Bruno')
INSERT INTO PESSOA VALUES (2, 'Carol')
INSERT INTO PESSOA VALUES (3, 'Flock')

Abra uma transação, execute o update abaixo e não efetue o Commit, deixe a transação aberta.

USE SUSPECT

BEGIN TRAN

UPDATE PESSOA SET NOME = 'Floki' WHERE ID = 3

CHECKPOINT

Abra o Gerenciador de Tarefas e encerre o processo do SQL Server, com isso iremos simular um crash no servidor.

Edite o arquivo de LOG (.ldf) do banco de dados com um editor hexadecimal e altere a primeira linha com Zeros e salve o arquivo.

Para editar o arquivo estou utilizado o aplicativo XVI32 que pode ser baixado gratuitamente no link: http://www.chmaas.handshake.de/delphi/freeware/xvi32/xvi32.htm

Inicie o serviço do SQL Server novamente e ao checarmos o status do database SUSPECT podemos ver que o mesmo está com o status Suspect.

Agora que já temos o banco de dados corrompido, vamos tentar recuperá-lo executando os comandos abaixo.

ALTER DATABASE [SUSPECT] SET EMERGENCY;
GO
ALTER DATABASE [SUSPECT] SET SINGLE_USER;
GO
DBCC CHECKDB (N'SUSPECT', REPAIR_ALLOW_DATA_LOSS) WITH NO_INFOMSGS, ALL_ERRORMSGS;
GO

Considerações sobre os comandos acima:

EMERGENCY:  Deixa o banco de dados com acesso limitado, somente quem for SYSADMIN acessa e desabilita o LOG do servidor.

SINGLE_USER: O nome é auto explicativo, deixa o database em modo de usuário único.

DBCC CHECKDB: Utilizado para verificar a integridade física e logica de um banco de dados, em breve farei um post mais detalhado a respeito do DBCC, o importante aqui é o argumento utilizado em conjunto com o DBCC, o REPAIR_ALLOW_DATA_LOSS, de forma bem superficial indica para o SQL Server que para recuperar o banco de dados uma certa perda de dados é aceitável.

Assim que os comandos forem executados, aparecerão algumas informações:

Dentre elas está a confirmação de que o log do banco de dados foi recriado e que se o banco de dados fazia parte de uma rotina com backup diferenciais e de logs a cadeia de restore foi rompida.

Msg 5172, Level 16, State 15, Line 5
The header for file 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\SUSPECT_log.ldf' is not a valid database file header. The PageAudit property is incorrect.
File activation failure. The physical file name "C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\SUSPECT_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.

Warning: The log for database 'SUSPECT' has been rebuilt. 
Transactional consistency has been lost. 
The RESTORE chain was broken, and the server no longer has context on the previous log files, 
so you will need to know what they were. 
You should run DBCC CHECKDB to validate physical consistency. 
The database has been put in dbo-only mode. 
When you are ready to make the database available for use, you will need to reset database options and delete any extra log files.

Porem se checarmos novamente o status do banco de dados já podemos verificar que o mesmo está ONLINE, porém em SINGLE USER.

Altere novamente o banco para o modo MULTI_USER.

ALTER DATABASE [SUSPECT] SET MULTI_USER

E agora vamos checar como está o registro que estava sendo alterado no momento do Crash.

Podemos notar que o SQL recuperou o banco de dados inclusive com a transação que estava sendo realizada concluída.

Agora que já recuperamos o banco de dados, podemos rodar um DBCC CHECKDB para verificarmos a integridade do banco de dados.

DBCC CHECKDB (N'SUSPECT') WITH ALL_ERRORMSGS;

E é isso, espero que tenham gostado do artigo.