A verdadeira data de criação de um banco de dados

Processed with VSCOcam with f2 preset

Olá,

Como descobrir a verdadeira data de criação de um banco de dados? A princípio, parece ser uma pergunta simples de responder e a resposta aparece de quase imediato: veja na create_date da sys.databases. Mas estamos falando da verdadeira data de criação de um banco de dados, aquela que permanece a mesma mesmo se for a base restaurada em uma instância diferente.

A verdade é que depende. Depende da versão do produto em que o banco de dados foi originado.

IMPORTANTE: O post faz referência a vários comandos e dados não documentados, como DBCC PAGE, metadados das páginas, etc.Use por sua conta em risco🙂

Início dos testes

Nosso objetivo aqui é mostrar o verdadeiro significado do campo create_date da sys.databases e mostrar que ela não é tão confiável assim para descobrir a real data de criação de uma base e que essa informação está disponível através da boot page no próprio banco de dados, porém depende da versão do SQL Server na qual o banco foi criado.

O servidor  utilizada para testes roda o SQL Server 2008 R2 Enterprise Edition.


-- Criando a base de testes
CREATE DATABASE MinhaBaseMinhaVida

-- Vamos checar a data de criação da base

SELECT NAME, CREATE_DATE FROM SYS.DATABASES D
WHERE NAME = 'MinhaBaseMinhaVida'  -- 2014-10-31 10:09:34.520

Até aqui nada demais… A data de criação da base neste momento que a sys.databases nos trouxe é fidedigna (porque a base foi criada diretamente e não foi restaurada). Então aqui, a informação passada pela sys.databases é verdadeira.

Vide quadro abaixo:

NAME

CREATE_DATE

MinhaBaseMinhaVida

2014-10-31 10:09:34.520

Boot Page aka página 9

Todo banco de dados possui uma Boot Page, que corresponde a página de número 9 e nela contém informações essenciais (pra não dizer críticas) para sobre o banco de dados em questão. Essa página é obrigatória para operações de inicialização  da base e se a mesma for corrompida e não houver backups para restaurá-la em caso de desastre, só um milagre resolverá o problema. Das várias informações úteis sobre o banco de dados, podemos supor que se em algum lugar é registrada a informação da verdadeira data de criação de um banco de dados, existem grandes chances desta informação estar na boot page.


DBCC TRACEON(3604)
DBCC PAGE ('MinhaBaseMinhaVida',1,9,3)

Campo de interesse: dbi_crdate

createDate1

Tirando um backup da base, vamos checar as informações através do cabeçalho do arquivo de backup:

RESTORE HEADERONLY FROM DISK =   'C:\TEMP\MinhaBaseMinhaVida.BAK'

CREATEDATE2

A data do campo DatabaseCreationDate equivale à data identificada no create_date, desconsiderando os milésimos.

Vamos restaurar o backup e observar o que realmente muda:


RESTORE DATABASE MinhaBaseMinhaVida from DISK = 'C:\TEMP\MinhaBaseMinhaVida.BAK'

SELECT NAME, CREATE_DATE FROM SYS.DATABASES D
WHERE NAME = 'MinhaBaseMinhaVida'  -- 2014-10-31 10:19:05.993

NAME

CREATE_DATE

MinhaBaseMinhaVida

2014-10-31 10:19:05.993

A data de criação da base mudou pra data de restauração. Confere, produção?

 SELECT  * FROM MSDB.DBO.RESTOREHISTORY R WHERE R.destination_database_name = 'MinhaBaseMinhaVida'

destination_database_name

restore_date

MinhaBaseMinhaVida

2014-10-31 10:19:05.867

Consultando a Boot page:

DBCC PAGE ('MinhaBaseMinhaVida',1,9,3)

CreateDate3

Aqui descobrimos o real significado da dbi_crdate: a data de criação da base naquela instância, que pode ser um create ou um restore, e por isso, não é uma data totalmente confiável…Um teste interessante pra ser feito aqui, é que se formos restaurar a base sobrescrevendo a antiga (com o uso efetivo do comando with replace) o dbi_crdate não será atualizado.

Mas ainda na boot page, temos outra data que deve ser verificada…

CreateDate4

Destacando:

m_fSeqNo = 26 m_blockOffset = 104 m_slotId = 64

dbi_dbccLastKnownGood = 1900-01-01 00:00:00.000 dbi_modDate = 2014-10-31

O campo dbi_modDate é similar à verdadeira data de criação inicial da base. O nome pode nos levar a pensar que essa data deve estar relacionada apenas à modificações na estrutura no banco de dados em questão mas podemos provar que de fato é a data que estamos procurando.

Vamos realizar alguns testes com a query abaixo. Ela faz um leitura na boot page e filtra somente campos que contenham date no nome. A ideia aqui é facilitar nossa vida e trazer o resultado em um formato mais amigável pra gente. Lembrando que usar dbcc page utilizando tableresults dispensa a necessidade de ativar o TF3604.


DECLARE @VAR AS TABLE
(
	ParentObject varchar(max),
	Object varchar(max),
	Field varchar(max),
	value varchar(max)
)

INSERT INTO @VAR
EXEC ('DBCC PAGE (''MinhaBaseMinhaVida'',1,9,3) WITH TABLERESULTS')

SELECT field, value FROM @VAR WHERE FIELD LIKE '%DATE%'

Field

value

dbi_crdate

2014-10-31 10:19:05.993

dbi_modDate

2014-10-31 10:09:35.737

Vamos realizar algumas modificações na estrutura da base pra ver se a tal da modDate é atualizada…

ALTER DATABASE MinhaBaseMinhaVida SET COMPATIBILITY_LEVEL = 80 -- Estava em 100
ALTER DATABASE MinhaBaseMinhaVida SET RECOVERY SIMPLE
ALTER DATABASE MinhaBaseMinhaVida ADD FILE (name= 'data2', filename = 'c:\temp\data2.ndf')

Se executarmos a query de verificação, vamos observar que as ambas as datas permanecem as mesmas.
Vamos fazer agora um attach e dettach e observar as datas.

NAME

CREATE_DATE

MinhaBaseMinhaVida

2014-10-31 11:14:23.623

A data de criação foi alterada na sys.databases. Ela corresponde agora ao exato momento em que o Attach ocorreu.

Vamos usar aquela consulta para verificar as data da boot page:

Field

value

dbi_crdate

2014-10-31 10:19:05.993 (mesma data de antes e não é a do attach!)

dbi_modDate

2014-10-31 10:09:35.737 (Firme e forte, sem mudanças)

E aqui outra descoberta! dbi_crdate não foi alterada mesmo com o attach. Isso derruba o mito (que parece ser intuitivo até…) de que a dbi_crdate sempre será equivalente à data da create_date da sys.databases.

Um último teste…fazer backup da base e restaurar em outra instância e conferir as datas…

RESTORE DATABASE MinhaBaseMinhaVida
FROM DISK = 'C:\TEMP\MinhaBaseMinhaVida.BAK'
WITH MOVE 'MinhaBaseMinhaVida' TO 'C:\TEMP\MD.MDF',
	 MOVE 'MinhaBaseMinhaVida_log' TO 'C:\TEMP\MD.LOG'

Field

value

dbi_crdate

2014-10-31 11:31:33.103

dbi_modDate

2014-10-31 10:09:35.737

Observe que agora a dbi_crdate foi alterada pois reflete a data de criação da base naquela instância (na prática, o restore é a criação de uma base… mas notem que a dbi_modDate permanece a mesma!

Podemos concluir que a dbi_modDate é a data de criação definitiva e imutável de uma determinada base.

Certo?

Depende. Infelizmente, nem sempre poderemos contar com essa data

O campo dbi_Moddate e o SQL Server 2000

Em nosso ambiente, tinhamos a tarefa de identificar a data real de criação das  bases do ambiente de produção, e checando a dbi_moddate topamos com uma data aparentemente padrão: 1900-01-01 e algumas poucas com datas diversas. A informação que temos é que as bases que possuem dbi_moddate  datando em 1900 são bases que vieram do SQL Server 2000. Vamos executar alguns testes e entender o que acontece:

O nosso cenário é um pouco diferente… A data está com valor default (de ano 1900). Sabemos que a base foi migrada de um servidor SQL Server 2000. Vamos refazer os mesmos procedimentos em uma base SQL 2000 então.

CREATE DATABASE MinhaBaseMinhaVida
go

SELECT * FROM  sysdatabases d where d.name = 'MinhaBaseMinhaVida' -- 2014-10-31 11:37:40.680

dbcc traceon (3604)
dbcc page ('MinhaBaseMinhaVida',1,9,3)
Uma importante descoberta aqui....

Algo importante de ser notado:

BootPage1

Cadê o dbi_moddate? Ele não existe nas boot pages do SQL Server 2005 e inferior (o que inclui 2000).

Próximos passos:

  • No SQL Server 2000: tirar backup da base MinhaBaseMinhaVida;
  • Restaurar a base no SQL Server 2008R2 (Restaurei com o nome MinhaBaseMinhaVida2000)
DECLARE @VAR AS TABLE
(
ParentObject varchar(max),
Object varchar(max),
Field varchar(max),
value varchar(max)
)

INSERT INTO @VAR
EXEC ('DBCC PAGE (''MinhaBaseMinhaVida2000'',1,9,3) WITH TABLERESULTS')

SELECT Field, value FROM @VAR WHERE FIELD LIKE '%DATE%'
Field value
dbi_crdate 2014-10-31 14:11:25.203
dbi_modDate 1900-01-01 00:00:00.000

1900-01-01 é a data padrão para o dbi_modDate para bases que foram restauradas de versões anteriores ao SQL Server 2008. Significa que para bases que sejam de versões anteriores, você não pode confiar neste campo.

Afinal, qual é a data de criação da base?

Alguns dos métodos disponíveis (os mais úteis) e algumas considerações em específico:

  • Dbi_crdate:  É a data de criação da base naquela instância em específico. Não é totalmente confiável pois a base pode ter vindo de outro servidor;
  • Dbi_moddate: É a data definitiva de criação da base.Se ela existir, é confiável e portanto, presentes em bases criadas à partir do SQL Server 2008, contando que essa data nunca tenha sido alterada na mão, já que é possível alterar conteúdo das páginas do SQL Server o que em geral é uma má (e perigosa) ideia;
  • Create_date (sys.databases): Data do último restore ou attach. Não é totalmente confiável por motivos já explicados, embora seja extensamente utilizada no mundo afora para respostas rápidas.
  • A data mais antiga que você encontrar na sys.objects de determinada base (independente do objeto, seja proc, tabela, function, etc) pode ser a mais próxima da data de criação de base, porém é muito raro e pouco provável que alguém vá criar uma base sem objeto algum. O ruim é que essa abordagem possui dois poréns:

1) Objetos podem ser dropados, então não necessariamente as datas são 100% confiáveis;

2) O banco de dados em questão pode ter sido criado usando uma base “template” (é um dos casos que temos em nosso ambiente). Neste caso, a data dos objetos não é confiável e então deveríamos considerar como “data de criação” a  data em que o deploy ocorreu em produção, e aí consideramos ou a data do primeiro restore (vide restorehistory ou dbi_crdate) ou a data de deploy (que é persistida em alguns processos em tabelas de controle criadas por usuário). Na ausência da dbi_moddate talvez seja a melhor forma de chegar na data de criação, porém essa possibilidade deve ser analisada com bastante cuidado.

Vale lembrar que, dependendo da pergunta que se pretende responder, talvez a data de deploy da base em produção, se for controlada através de uma mecanismo particular pode servir para responder qual é a data de criação de uma base (e não é necessariamente a verdadeira). Imagine que uma base BDABC foi criada em 2010 em desenvolvimento e só subiu pra produção em 2013. Dependendo do caso, o “nascimento” dela pro negócio foi em 2013 quando o deploy foi feito pra ser utilizado na vera e não a data em que a base foi realmente concebida (3 anos antes). É algo a se pensar também…


Espero que o artigo tenha sido útil e fique à vontade para corrigir, comentar, opinião, críticar, etc.
[]’s


Referências

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s