T-SQL Tuesday #20 – Melhores Práticas

Neste mês o tema escolhido pelo Sr. Amit Banerjee (blog | twitter) foi: Melhores Práticas,,,

A algum tempo atrás escrevi um post com “Dicas para otimizar suas funções SQL”,,, vou adicionar algumas coisas que acho interessante com este post aqui.

  • Comentários,,,,

Lembra daquela procedure que fazia uma validação de alguma coisa em algum lugar ??? Lembra por que você declarou aquele campo bit no começo ??? Não? tem certeza que sabe? acha que era para alguma coisa importante?

Uma coisa que acho muito importante em todo o código, mas são poucas as pessoas que fazem direito e menos ainda as que fazem, é comentar o que ele faz,,,

Não custa muito adicionar algumas linhas com algum tipo de descritivo do que aquilo deveria fazer, quem fez, quando fez, qual a versão, algum exemplo,,,

Lembre-se: Uma hora ou outra o código pode precisar de manutenção,,, ela pode ser feita por você ou outra pessoa,,, em todo o caso,,, é sempre bom ter alguma coisa para te ajudar a lembrar,,,

Ex:

/*
Nome: usp_mostra_nome_base
Versão: 2.0
Data de criação: 11-07-2011
Data da última modificação: 12-07-2011

Autor: Ricardo Leka Roveri
Últuma modificação executada por: Ricardo Leka Roveri

Script:
Esta procedure server para listas o nome das bases existentes no sistema.

Exemplo
exec usp_mostra_nome_base

Versão 1:
Autor: Ricardo Leka Roveri

nesta versão a proc faz XYZ

Versão 2:
Autor: Ricardo Leka Roveri

nesta versão a proc faz XYZ ordenado por data de criação

*/

Outra coisa interessante seria comentar partes do código,,, não precisa escrever um livro do motivo que você está fazendo aquele join entre 20 tabelas mas, de uma forma clara, escrever o objetivo dessa bagunça,,,

  • NOLOCK,,,

Você é um fanático por NOLOCK? Legal,,, nada contra,,, mas se vai usar isso umas 40 vezes dentro de uma procedure porque você não declara ele como:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITED;

é legal, ajuda, mais simples pra você e para qualquer outra pessoa que veja seu código…

  • Lembrete,,,

Lembre-se:

A maior parte de vocês não desenvolve coisas pra vocês,,, vocês desenvolvem coisas pra outras pessoas usarem…

Não é porque na sua maquina tudo funciona direitinho que quando for para produção tem que funcionar,,, Você precisa testar,,, faça teste de carga… stresse sua aplicação até ela parar,,, 10,,, 100,,, 1000,,, acessos simultâneos,,,

Existem muitas ferramentas que fazem teste de carga. Ex.: JMeter, o próprio SQL Profiler, etc..

Corrompendo um Banco SQL

Qual a necessidade de criar uma base corrompida?

Pra que você precisa desse tipo de coisa?

Você precisa treinar…

Mesmo que saiba o que fazer, é importante treinar para situações complicadas…

É melhor fazer muita tentativa em erro em um ambiente controlado do que no ambiente de produção,,, certo?

Então,,, antes de mais nada… eu sei que você sabe,,, mas não custa nada relembrar,,,

NUNCA FAÇA ISSO EM PRODUÇÃO !!!

Bom,,, com isso em mente,,, vamos começar,,,

1. Vamos criar uma base:

CREATE DATABASE [corrompeu]
GO

2. Vamos alterar o modo de recovery da base:

alter database corrompeu
set recovery full
GO

3. Agora vamos colocar uma tabela:

use corrompeu
GO

create table vendas
(
vendasID int identity,
clienteID int default convert(int, 100000 * RAND()),
vendaData datetime default getdate(),
vendaTotal money
)
GO

4. Adicionamos um índice pra dar gosto…

create clustered index vendaCI on vendas (vendasID)
GO

5. Colocamos uns dados,,,

set nocount ON
GO

declare @conta INT
select @conta = 0
while (@conta < 50000)
begin
    insert into vendas (vendaTotal)
    values (100*RAND())
    select @conta = @conta +1
end
GO

7. E vamos fazer uns backups

use master
GO

backup database corrompeu
to disk = ‘d:\db01\local\corrompeu_1.bak’
with init
go

backup log corrompeu
to disk = ‘d:\db01\local\corrompeu_2.trn’
go

8. Bom,,, com os backups feitos,,, vamos ver as páginas que foram criadas,,,

dbcc ind (‘corrompeu’,‘vendas’,1)
GO

9. Escolha uma página e coloque no lugar do XXXXX

DBCC TRACEON (3604)
GO
dbcc page(‘corrompeu’,1,XXXXX,3)

Você deve ver alguma coisa do tipo:

A página que eu escolhi foi a 1:493. Meu vendasID vai do registro 24256 até 245000.

Agora começa a ficar legal….

10. Vamos colocar a base offline:

alter database corrompeu
set offline
GO

11. Agora um simples cálculo…

select 493*8192
GO

Temos o número em decimal da localização da página no arquivo .mdf

12. Com esse número vamos utilizar um editor Hexadecimal para achar a linha dentro do arquivo .mdf.

  • Dentro do editor de Hexadecimal, abra o arquivo .mdf (neste caso D:\DB01\Corrompeu.mdf).
  • Clique em “Localizar” e escolha “Ir Para”.
  • Escolha a opção “DEC”, digite ou cole o resultado do cálculo acima e depois cliente em “HEX”, ele vai converter o valor para Hexadecimal.

  • clique em “OK”
  • Altere a linha onde o cursor esta piscando para 00 (zero-zero), ela vai ficar em vermelho.

  • Salve o arquivo.

13. Agora dentro do SQL vamos voltar com a base online:

alter database corrompeu
set online
GO

14. Usando o DBCC CHECKDB, vamos ver se a base está realmente corrompida…

Legal,,, temos uma base corrompida…

15. vamos tentar um select na tabela,,, e olha lá o erro,,,

Bom,,, legal… temos uma base corrompida,,, e agora?

Agora fica legal… o objetivo é deixar a base operacional sem perder informação… imagine que essa é sua base de produção e justamente essa tabela é a folha de pagamento,,, olha que legal…

Uma dica: tentei fazer o processo de restore no SQL Server Denali CTP 1 e não consegui restaurar apenas a página, tive que remover ela e reinserir os dados através de outra base, fiz o mesmo processo de restore apenas da página no SQL Server 2008 R2 e funcionou sem problema.

Se alguém precisar de ajuda é só deixar o comentário…

ATUALIZAÇÃO:

Segue o link do SkyDrive com a base, backup e o script desse exemplo:

https://skydrive.live.com/?cid=5145b04265f2979d&sc=documents&id=5145B04265F2979D%21171#