quarta-feira, 18 de março de 2015

Encontrando usuários e suas sessões no SQL

Vamos descobrir quais usuários estão conectados e quantas sessões cada um possui no momento?

Esta informação é muito útil quando vamos iniciar uma janela de manutenção ou quando queremos saber se há um aumento na quantidade de sessões por usuário. Podemos verificar quem está conectado no momento, avisar que o SQL vai parar e então iniciar aquela manutenção agendada.

De onde vem estas informações?

Estas informações são armazenadas nas DMVs (Dynamic Management Views), novidade na versão 2005 do SQL e mantida até as versões atuais.

Uma DMV é como uma View onde podemos armazenar o resultado de um Select. Neste caso, estamos trazendo as informações da DMV chamada sys.dm_exec_sessions:

 

Conhecimentos basicos sobre Storage

O que é

Uma storage nada mais é do que um dispositivo com um ou mais discos capaz de se conectar aos servidores o prover espaço em disco da mesma forma que um disco local. É um hardware (pode ser um servidor comum ou equipamento dedicado à função de storage) com um sistema operacional (exclusivo ou adaptado como Linux, CentOS, Windows, etc.) que, através de conexões como Ethernet ou Fibra óptica, podemos conectar a um ou mais servidores. Podemos por exemplo, pegar um servidor com 6 discos, utilizarmos dois discos em RAID1 para o sistema operacional e os outros quatro discos em RAID5, para dividirmos em volumes que serão utilizados por nossos servidores. Podemos comprar uma caixa com encaixes para discos que faz exatamente a mesma coisa mas não possui monitor, teclado nem acesso via RDP ou SSH. Em ambos os casos, utilizamos apenas um navegador para nos conectarmos e configurarmos os volumes que serão apresentados aos servidores.

 

Principais tipos

Vamos estudar os três principais tipos encontrados no mercado, que provavelmente você vai se deparar ou vão te oferecer quando pretender adquirir uma storage. É muito importante para um analista saber orientar seu gestor que tem o controle dos investimentos sobre as características de cada tipo, ou ainda melhor, para os gestores desta nova geração em que na maioria das vezes possuem um excelente passado técnico.

DAS

DAS significa Direct Attached Storage, são dispositivos diretamente conectados ao servidor através de USB, e-SATA ou até mesmo Ethernet. É o tipo mais simples, normalmente não oferecem técnicas de proteção a dados exceto alguns modelos que oferecem até RAID mas que geralmente são configurados em RAID0 para oferecerem uma performace melhor pois seu hardware é focado em baixo custo e por isso o desempenho é fraco. Sua aparência na maioria das vezes é como a de um disco externo, um pouco maior de acordo com a quantidade de discos mas existem storages DAS maiores, como storages para racks com 16 ou até mais discos. A comunicação é em nível de arquivo, ou seja, os outros servidores enxergam como um compartilhamento comum na rede.

Para ficar mais claro, veja a topologia abaixo. Repare que as storages DAS estão conectadas diretamente a um servidor ou desktop:

NAS

A storage NAS ou Network Attached Storage é um servidor com a mesma finalidade da DAS conectado a rede ao invés de se conectar diretamente nos servidores. Estes servidores não são desenvolvidos para tarefas computacionais em geral, apesar de tecnicamente ser possível executar outros softwares neles. Geralmente não possuem teclado ou monitor, e são configuradas através de um browser. Os protocolos utilizados pelo NAS são o NFS (popular em sistemas UNIX), ou CIFS/SMB (Common Internet File System/Server Message Block) em ambientes Windows, além do tradicional FTP. Existem alternativas open source para implementações caseiras de NAS, como o FreeNAS, o Openfiler e o NASLite. Apesar de serem soluções caseiras, é comum vermos este tipo de equipamento em empresas e datacenters. Assim como a DAS, a storage NAS também é acessada a nível de arquivo, com a diferença de ser conectada a um switch ao invés de estar conectada diretamente a um servidor como acontece com a DAS e, em algumas vezes, você encontrará um dispositivo desses conectado através de fibra. Neste caso, o hardware todo é mais robusto e a performance bem maior.

SAN

Storage Attached Network é o melhor dos mundos para escalabilidade, disponibilidade, proteção de dados e performance. Utiliza uma rede específica para armazenamento, de fibra ótica (protocolo Fiber Channel) ou par trançado (protocolo iSCSI). A comunicação com os servidores não é mais a nível de arquivo mas sim a nível de blocos (como um HD), o que possibilita que os servidores enxerguem estes volumes como unidades de disco locais, idêntico a um HD interno, por exemplo. Por possuírem uma série de redundâncias (fontes de alimentação, discos, controladoras, etc.) e pelo investimento necessário são utilizadas em ambientes de missão crítica onde a disponibilidade deve ser de 24x7. Existem SAN atualmente que fazem coisas fantásticas com os dados, provendo segurança e performance confiáveis. Estas storages geralmente possuem o tamanho de um rack (embaladas até parecem um rack) ou de vários racks lado a lado.

 

Continuando um restore de onde parou

Durante um processo de restore de uma grande base um outro alguém reiniciou os serviços do SQL. Como resultado, a base ficou em "restoring":

Veja como continuar o restore.

 

Como o restore era de uma base muito grande e portanto demorado, ao invés de iniciar novamente pude continuar de onde parou com a cláusula WITH RESTART. Com isso, conseguimos manter o tempo de restore e deixamos a base online novamente, pronta para receber as conexões:

Segue a query:

RESTORE DATABASE TESTE FROM DISK = 'c:\Backup\teste.bak'
WITH RESTART

 

Quando esta instância foi instalada?

Precisando saber quando o Sqlserver foi instalado, o script abaixo pode ajudar

 

 

SELECT createdate AS [SQL Server Install Date]
FROM sys.syslogins
WHERE [sid] = 0x010100000000000512000000;
Resultado:

Com este pequeno select da tabela sys.syslogins você consegue saber quando o SQL foi instalado no servidor, informação útil muitas vezes.

 

Mostrando o número das linhas no SQL

Quando o SQL exibe uma mensagem de erro dizendo que a sintaxe de uma query está errada na linha 123, como você faz para encontrar esta linha?

Bem simples. Abra o MSSQL Server Management Studio, clique em Tools (ou Ferramentas) e depois em Options:

 

 

Diversas opções podem ser alteradas aqui. Vamos encontrar a que exibe o número das linhas em uma query.

 

 

Veja na figura acima como é fácil. Expanda Text Editor, Transact-SQL e clique em General. No painel do lado direito marque a opção Line numbers e clique em OK. Pronto, era só isso mesmo.

 

 

Além disso, imagine que sua query ou procedure tenha muitas linhas e o erro está na linha 972. Você não vai querer rolar a tela até chegar na linha 972. Utilize o mesmo atalho do Bloco de Notas que te direciona direto pra linha solicitada. Pressione Ctrl+G e veja:

 

Redundant Array of Independent Disks RAID

RAID significa "Redundant Array of Independent Disks" ou conjunto redundante de discos independentes. A diferença para usuários comuns vem na performance muitas pessoas optam por fazer o Raid 0 . No Raid existem vários níveis são eles:

RAID Nível 0

Esse nível também é conhecido como “Striping” ou “Fracionamento”.
No RAID 0 os dados do são divididos em pequenos segmentos e distribuídos entre os diversos discos disponíveis, o que proporciona alta performance na gravação e leitura de informações, porém não oferece redundância, ou seja, não é tolerante a falhas. O aumento da performance no RAID 0 é obtido porque se vários dados fossem gravados em um único disco esse processo aconteceria de forma “Seqüencial” já nesse nível os dados são distribuídos entre os discos ao mesmo tempo.

O RAID 0 pode ser usado para estações de alta performance (CAD, tratamento de imagens e vídeos), porém não é indicado para sistemas de missão-crítica.

RAID Nível 0+1

O RAID 0+1 é uma combinação dos níveis 0 (striping) e 1 (mirroring). No RAID 0+1 os dados são divididos entre os discos e duplicados para os demais discos. Assim temos uma combinação da performance do RAID 0 com a tolerância à falhas do RAID 1. Para a implantação do RAID 0+1 são necessários no mínimo 4 discos o que torna o sistema um pouco caro.
Ao contrario do que muitos pensam, o RAID 0+1 não é o mesmo do RAID 10. Quando um disco falha em RAID 0+1 o sistema se torna basicamente um RAID 0.

O RAID 0+1 pode ser utilizado em estações que necessitam de alta performance com redundância como aplicações CAD e edição de vídeo e áudio.

RAID Nível 1

O nível 1 também é conhecido como "Mirror", “Duplexing” ou “Espelhamento”.
No RAID 1 os dados do são gravados em 2 ou mais discos ao mesmo tempo, oferecendo portanto redundância dos dados e fácil recuperação, com proteção contra falha em disco. Uma característica do RAID 1 é que a gravação de dados é mais lenta, pois é feita duas ou mais vezes. No entanto a leitura é mais rápida, pois o sistema pode acessar duas fontes para a busca das informações.

O RAID 1 pode ser usado para Servidores pelas características de ter uma leitura muito rápida e tolerância à falhas.

RAID Nível 2

O nível 2 também é conhecido como “Monitoring”.
O RAID 2 é direcionado para uso em discos que não possuem detecção de erro de fábrica, pois “adapta” o mecanismo de detecção de falhas em discos rígidos para funcionar em memória.

O RAID 2 é muito pouco usado uma vez que todos discos modernos já possuem de fábrica a detecção de erro.

RAID Nível 3

No RAID 3 os dados são divididos (em nível de bytes) entre os discos enquanto a paridade é gravada em um disco exclusivo. Como todos os bytes tem a sua paridade (acréscimo de 1 bit para identificação de erros) gravada em um disco separado é possível assegurar a integridade dos dados para recuperações necessárias.

O RAID 3 também pode ser utilizado para Servidores e sistemas de missão-critica.

RAID Nível 4

O RAID 4 é muito parecido com o nível 3. A diferença é que além da divisão de dados (em blocos e não bytes) e gravação da paridade em um disco exclusivo esse nível permite que os dados sejam reconstruídos em tempo real utilizando a paridade calculada entre os discos. Além disso a paridade é atualizada a cada gravação, tornado-a muito lenta.

O RAID 4 pode ser utilizado para sistemas que geram arquivos muito grandes como Edição de vídeo, porque a atualização da paridade a cada gravação proporciona maior confiabilidade no armazenamento.

RAID Nível 5

O RAID 5 é semelhante ao nível 4, exceto o fato de que a paridade não é gravada em um disco exclusivo para isso e sim distribuída por todos os discos da matriz. Isso faz com que a gravação de dados seja mais rápida, porque não existe um disco separado do sistema gerando um “Gargalo”, porém como a paridade tem que ser dividida entre os discos a performance é um pouco menor que no RAID 4.

O RAID 5 é amplamente utilizado em Servidores de grandes corporações por oferecer uma performance e confiabilidade muito boa em aplicações não muito pesadas. E normalmente são utilizados 5 discos para aumento da performance.

RAID Nível 6

O RAID 6 é basicamente um RAID 5 porém com dupla paridade.

O RAID 6 pode ser utilizado para sistemas de missão-critica aonde a confiabilidade dos dados é essencial.

RAID Nível 7

No RAID 7 as informações são transmitidas em modo assíncrono e são controladas e cacheadas de maneira independente, obtendo performance altíssima.

O RAID 7 é raramente utilizado pelo custo do Hardware necessário.

RAID Nível 10

O RAID 10 precisa de no mínimo 4 discos rígidos para ser implantado. Os dois primeiros discos trabalham com striping enquanto os outros dois armazenam uma cópia exata dos dois primeiros, mantendo a tolerância à falhas. A diferença básica desse nível para o RAID 0+1 é que sobre certas circunstancias o RAID 10 pode sustentar mais de uma falha simultânea e manter o sistema.

O RAID 10 pode ser utilizado em servidores de banco de dados que necessitem de alta performance e alta tolerância a falhas como em Sistemas Integrados e Bancos

Agent XPs disabled

Quem nunca se deparou com esta situação e por isso pensei que seria útil escrever a respeito. Os jobs não estavam sendo executados mas o SQL Server Agent estava rodando nos serviços do Windows. Clicando com o botão direito sobre o Agent as opções de Start, Stop e Restart estão lá mas não é possível iniciar com o seguinte erro:

 

 

 

Ao lado do SQL Server Agent, um aviso entre parênteses:

 

 

Isto acontece porque nas configurações avançadas, o Agent XPs está com o valor 0. Geralmente este valor é automaticamente configurado para 1 na instalação mas por algum motivo esta configuração falhou e agora está com o valor 0. Também acontece se a base MSDB estiver com acesso RESTRICTED USER.

Para resolver vamos ativar as configurações avançadas e configurar o Agent XPs utilizando o sp_configure. Através do sp_configure podemos alterar diversas configurações do SQL, vamos executar sp_configure apenas para ver as configurações atuais:

 

 

Nesta lista temos os itens que podemos configurar e os possíveis valores mínimos, máximos, configurados e utilizados atualmente. Repare que apesar de termos diversas configurações, a opção Agent XPs não está nesta lista, mas na linha 15 temos a opção show advanced options com os valores 0 no configurado e também 0 no utilizado atualmente.

Vamos alterar para 1, para que as opções avançadas passem a fazer parte desta lista:

sp_configure ‘show advanced options’,1

A sintaxe é sempre esta – sp_configure ‘opção entre aspas simples’, valor

 

 

Veja que a mensagem diz que a configuração mudou de 0 para 1 mas é necessário executar o RECONFIGURE para que esta configuração entre em vigor. Para entendermos melhor, vamos executar o sp_configure novamente para vermos as configurações atuais:

 

 

 

Veja que agora a configuração é 1 mas o que está em execução ainda é 0, ou seja, ainda não foi aplicado. Agora vamos rodar o RECONFIGURE:

 

 

E agora vamos ver as configurações novamente com o sp_configure:

 

 

Agora temos todas as opções configuráveis, veja que nosso Agent XPs está com o valor 0 mas já vamos alterá-lo:

 

sp_configure ‘Agent XPs’,1
RECONFIGURE 

 

Dê um refresh e veja que o Agent já está normalizado. Pode ser que seja necessário iniciá-lo manualmente, ou seja, clicar com o direito e depois em Start.

 

Identificando o tempo de Backup /Restore

Olá Pessoal,

 

 

Hoje me perguntaram como fazer para identificar o tempo de backup/restore em execução.

Sendo assim, resolvi postar o script capaz de trazer esta informação.

 

 

 

-- Verifica Tempo restante de Backup /restore

--  Funciona no SQLSEVER 2005, 2008 e 2008 R2

 

SELECT start_time,

       (total_elapsed_time/1000/60) AS MinutesRunning,

       percent_complete,

       command,

       b.name AS DatabaseName,

              -- MASTER will appear here because the database is not accesible yet.

       DATEADD(ms,estimated_completion_time,GETDATE()) AS StimatedCompletionTime,

      (estimated_completion_time/1000/60) AS MinutesToFinish

FROM  sys.dm_exec_requests a

          INNER JOIN sys.DATABASES b ON a.database_id = b.database_id

WHERE command LIKE '%restore%'

          OR command LIKE '%backup%'

          AND estimated_completion_time > 0

Oracle x Db2 comparativo

Pessoal, achei este material  legal ..  e resolvi compartilhar

A instalação em Oracle: com root criamos os grupos, usuário Oracle e nele fizemos a instalação de binários, criação de instância e para RAC segue a mesma linha. Se precisamos de mais uma instância criaremos mais um usuário. Em DB2: pode ser instalado em um usuário normal o binário, mas é sugerido instalar o binário como root por ser mais seguro não apagar os binários erroneamente. Após isso cada usuário de SO pode criar a sua instância, seu(s) database(s).

Os usuários em Oracle: dentro da instância create user. Em DB2: é necessário que o usuário seja do SO.

As configurações realizadas em Oracle: do banco e da instância é tudo junto. Em DB2: existe do DB (banco de dados) é da DBM (instância) essas são separadas.

Os logs de alertas do banco em Oracle: Quem nos auxilia muito é ‘Alert.log’ além de possuirmos os trace files. Em DB2: tem um semelhante com o nome de db2diag.log (inclusive este db2diag.log possui uma ferramenta para filtro do db2diag.log chamada db2diag). O List History File (db2 list history …) armazena informacoes sobre backup, restore, criacao – alteracao – delecao de tablespaces, quando uma tabela sofre alguma alteracao ou reorganizacao etc (db2 list history …).

As tablespaces tem o mesmo príncípio mas em Oracle: Temos os Datafiles. Em DB2: Temos os Conteiners.

Comparações dos comandos entre os dois:

No Oracle temos o Automatic Storage Management (ASM) e no DB2 Automatic Storage Table Space que trabalha exclusivamente com Storage, diferente do ASM nesse ponto.

Também tem uma ferramenta semelhante (ou melhor) de SQL LOADER (sqlldr) que é DB2 Load Utility, esse teria que instalar e começar a rodar, mas parece melhor.
Outras ferramentas de exportação e importação tipo o DATA PUMP do Oracle, me parecem meio fracas, chamam DB2 Export Utility e DB2 Import Utility. Existe outras duas a DB2LOOK Utility que exporta todo o database em DDL e DB2MOVE Utility que copia ou move schemas entre databases, também executa as funções do Export Utility e Import Utility acima citado.

O Oracle RAC tem uOraclem concorrente forte (no meu ponto de vista nesse momento, sem testar é claro) chamado pureScale que parece realmente melhor que o RAC, pois vem de toda a expertise da IBM em trabalhar com processamento distribuído.

Também possui o particionamento de tabelas, pouco diferente, terei que executar testas para citar corretamente as diferenças.

As views materializadas do Oracle são chamados de MQT no DB2, a idéia é a mesma.

A compressão de dados do DB2, segundo o instrutor é bem melhor que do Oracle, no entando disse que quase nem é necessário executar rebuild de indices quando temos muitas exclusões, que esse processo de compactação se encarrega disso. Esse sim, merece um teste com um comparitivo forte entre eles, quero ver se faço isso, mas não deve ser em breve.

Uma visão geral dessa comparação:

 

 

O IBM DB2 versão 9.7 já possui um compilador próprio para PL/SQL, sendo assim não precisa ficar ‘executando um de – para’ em toda a análise, já faz a compilação e grava da forma como o interpretador precisa. Para o TSQL (SQL Server e Sybase) que é bem parecido com SQL PL do DB2 existe esse de – para, passando pelo mesmo compilador gravando da forma que o interpretador precisa.

O interpretador nesse caso será o mesmo para as duas saídas, a figura abaixo mostra isso:

Para que esse interpretador funcione, essa opção precisa ser configurada DB2_COMPATIBILITY_VECTOR, abaixo quais as features que podem ser habilitadas, as com * precisam fazer o procedimento de parar e iniciar a instância. Para habilitar todas de uma vez utilizar palavra ORA:

Criando um database com todas as features habilitadas:

Obs.: O database tem que ser criado depois que é habilitada a compatibilidade ou não serão utilizadas, pois ficará um database nativo DB2.

Alguns tipos de dados e onde eram os maiores problemas nas migrações em versões anteriores, que agora podem não ser tão problemáticas:

Uma outra coisa que achei interessante (ou não, a prática daria essa resposta) é que pode ‘misturar’ o PL/SQL, TSQL e SQL PL no desenvolvimento dos mesmos objetos (function or procedures), poderia rolar pegar o que cada uma tem de melhor e fazer acontecer, agora, isso como mencionei somente o desenvolvimento do dia a dia daria a resposta, mas seria interessante avaliar.

Itens que no PL/SQL estão funcionais são alguns que utilizo diariamente e acabei listando abaixo sem ter certeza como era/é no DB2 (precisaria testar tudo para dar um veredito final e ai sim ter certeza):
– Os cursores, para retornos em procedures;
– Utilização normal de de Packages.Procedures e Packages.Funcitions;
– Os privilegios para outras roles (usuários) executar, normal;
– Utilização do %type para tabela.campo e %rowtype para tabela na declaração de variáveis;

 

Verificando consumo de CPU por banco de dados

Verificando consumo de CPU por banco de dados

Olá pessoal, o script abaixo é capaz de verificar o consumo de CPU por database. Ele poder se muito útil na administração de ambiente.

WITH DB_CPU_Stats

AS
(SELECT DatabaseID, DB_Name(DatabaseID) AS [DatabaseName], SUM(total_worker_time) AS [CPU_Time_Ms]
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY (SELECT CONVERT(int, value) AS [DatabaseID]
FROM sys.dm_exec_plan_attributes(qs.plan_handle)
WHERE attribute = N'dbid') AS F_DB
GROUP BY DatabaseID)
SELECT ROW_NUMBER() OVER(ORDER BY [CPU_Time_Ms] DESC) AS [row_num],
DatabaseName, [CPU_Time_Ms],
CAST([CPU_Time_Ms] * 1.0 / SUM([CPU_Time_Ms]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CPUPercent]
FROM DB_CPU_Stats
WHERE DatabaseID > 4 -- system databases
AND DatabaseID <> 32767 -- ResourceDB
ORDER BY row_num OPTION (RECOMPILE);

 

ENTENDENDO OS DEADLOCKS

Os DeadLocks ocorrem quando existe um ciclo de dependência entre duas ou mais transações pelo mesmo recurso. Uma transação (T1) pode adquirir um ou mais recursos (por exemplo, locks). Se o recurso sendo adquirido por T1 já estiver sendo utilizado por outra transação (T2), T1 terá que aguardar a segunda transação (T2) liberar o recurso desejado. Neste caso, dizemos que T1 tem uma dependência de T2, que mantêm o recurso.

Agora imagine que a transação que mantêm o recurso (T2), também quer adquirir um recurso que está sendo utilizado pela primeira transação (T1). Esta situação ocasiona o famoso deadlock - ambas as transações não podem liberar os recursos que elas utilizam até elas serem concluídas (commit) ou desfeitas (rollbak) e estas transações não podem ser concluídas ou desfeitas porque elas estão aguardando por recursos uma das outras. Confuso?

Para tentar melhorar o entendimento, vamos a um exemplo:

Imagine que você possui uma aplicação e que a mesma abre duas transações no servidor, T1 e T2. A transação T1, adquiri um lock exclusivo na tabela Supplier. A transação T2, adquiri um lock exclusivo na tabela Part e também tenta adquirir um lock na tabela Supplier. A transação T2 não pode obter o lock porque T1 já possui o recurso, sendo assim, a transação T2 é bloqueada e fica aguardando pela conclusão da transação T1.

Enquanto isso, a transação T1 também tenta adquirir um lock na tabela Part, mas não pode obter o lock porque a transação T2 já possui o recurso. As transações não podem liberar os recursos até que elas sejam efetivadas (commit) ou desfeitas (rollback), porém, as transações não podem ser efetivadas ou desfeitas porque para continuar, estão aguardando pelo recurso uma da outra. Ou seja, T1 espera pela conclusão de T2 que espera pela conclusão de T1.

Na ilustração abaixo, a Transação 1 está aguardando a Transação 2 liberar o Lock na tabela Part, enquanto a Transação 2 também está aguardando a Transação 1 liberar o Lock na tabela Supplier.

Para resolver o deadlock, uma das transações do ciclo precisa ser derrubada e para escolher a "vítima" do deadlock, o SQL Server 2000 verifica todas as threads que estão participando da transação e o quanto estão sendo utilizadas. Geralmente, o SQL Server escolhe a thread que esta trabalhando menos para ser a "vítima" do deadlock. Quando um deadlock ocorre, o usuário recebe a seguinte mensagem de erro (Error 1205):

Your transaction (process ID #52) was deadlocked on {lock | communication buffer | thread} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.

O DBA também pode verificar a ocorrência de deadlocks no error log do SQL Server. Por default, os deadlocks não são logados no error log do SQL Server mas o DBA pode habilitar esta funcionalidade ativando os trace flags 3605 e 1204 no QA.

-- Ativa os trace flags
dbcc traceon (1204, 3605, -1)
go

-- Mostra os trace flags ativos no servidor
dbcc tracestatus(-1)
go

O trace flag 1204 coleta informações sobre os processos e os recursos utilizados quando um deadlock for detectado e o trace flag 3605 escreve estas informações para o error log do SQL Server.

Uma vez estando ativos estes trace flags, sempre que ocorrer um deadlock o SQL Server adicionará em seu erro log uma mensagem semelhante a apresentada abaixo:

Deadlock encountered .... Printing deadlock information
2005-04-06 10:31:09.01 spid3                          
2005-04-06 10:31:09.01 spid3     Wait-for graph       
2005-04-06 10:31:09.01 spid3                          
2005-04-06 10:31:09.01 spid3     Node:1               
2005-04-06 10:31:09.01 spid3    
RID: 16:1:112430:3             CleanCnt:1 Mode: U Flags: 0x2
2005-04-06 10:31:09.01 spid3      Grant List 2::                                            
2005-04-06 10:31:09.01 spid3        Owner:0x6f724b60 Mode: U        Flg:0x0 Ref:0 Life:00000001...
2005-04-06 10:31:09.01 spid3       
SPID: 191 ECID: 0 Statement Type: UPDATE Line #: 352
2005-04-06 10:31:09.01 spid3        Input Buf: RPC Event: sp_deadlock1             
2005-04-06 10:31:09.01 spid3      Grant List 3::                                       
2005-04-06 10:31:09.01 spid3      Requested By:                                        
2005-04-06 10:31:09.01 spid3        ResType:LockOwner Stype:'OR' Mode: U SPID:68 ECID:0....
2005-04-06 10:31:09.01 spid3                                                                
2005-04-06 10:31:09.01 spid3     Node:2                                                     
2005-04-06 10:31:09.01 spid3    
RID: 16:1:101962:22            CleanCnt:1 Mode: X Flags: 0x2
2005-04-06 10:31:09.01 spid3      Grant List 3::                                            
2005-04-06 10:31:09.01 spid3        Owner:0x6b119400 Mode: X        Flg:0x0 Ref:0 Life:02000000...
2005-04-06 10:31:09.01 spid3       
SPID: 68 ECID: 0 Statement Type: UPDATE Line #: 251
2005-04-06 10:31:09.01 spid3        Input Buf: RPC Event: sp_deadlock2
2005-04-06 10:31:09.01 spid3      Requested By:                                    
2005-04-06 10:31:09.01 spid3        ResType:LockOwner Stype:'OR' Mode: U SPID:191...
2005-04-06 10:31:09.01 spid3     Victim Resource Owner:                         
2005-04-06 10:31:09.01 spid3      ResType:LockOwner Stype:'OR' Mode: U SPID:191...


Com o log acima é possível obter as seguintes informações:

-- As conexões que causaram o deadlock ==> SPID: 191 e SPID: 68
-- A base de dados ==> RID: 16 (select db_name(16), para saber o nome da base)
-- Os objetos envolvidos no deadlock ==> procedures sp_deadlock1 e sp_deadlock2
-- O número das linhas dentro das procedures onde provavelmente ocorreu o deadlock ==>  UPDATE Line #: 352 e UPDATE Line #: 251

Neste exemplo, se abrirmos as procedures sp_deadlock1 e sp_deadlock2 e navegarmos até o número das linhas indicado, teremos os statements que causaram o deadlock.

MINIMIZANDO OS DEADLOCKS

É muito difícil eliminar os DeadLocks completamente, entretanto, o número de deadlocks pode ser minimizado. Minimizando os deadlocks, podemos aumentar o throughput das transações e reduzir o overhead do sistema.

Algumas das atividades que um DBA ou desenvolvedor podem estar reallizando para minimizar a ocorrência de deadlocks são as seguintes:

A) Acessar os objetos na mesma ordem: Se todas as transações acessarem os objetos na mesma ordem, será pouco provável ocorrer um deadlock. No exemplo abaixo, se duas transações concorrentes obterem lock na tabela Supplier e depois na tabela Part, uma delas ficará bloqueada na tabela Supplier até a outra transação terminar, então, a segunda continua e o DeadLock não ocorrerá.



B) Evitar a interação de usuários nas transações: Deve-se evitar transações de escritas que incluem a interação de usuários, porque a velocidade de execução de um batch sem a intervenção de usuários é muito maior em relação ao tempo de resposta de uma query executada manualmente por um usuário. Por exemplo, se uma transação está esperando por uma entrada (input) de um usuário e o usuário foi tomar um cafezinho, a transação ficará esperando para poder ser concluida. Mesmo se não ocorrer uma situação de deadlock, outras transações que acessem o mesmo recurso serão bloqueadas esperando que a transação seja concluída ou desfeita.

C) Fazer transações curtas e em um único batch: Um deadlock ocorre tipicamente quando executamos transações de longa duração concorrendo no mesmo objeto. Em uma transação muito longa, a possibilidade de locks exclusivos ou de update é muito maior,  o que bloqueia outras atividades e ocasiona possíveis situações de DeadLocks. Procure manter as transações em um único batch (uma batch termina quando você coloca a palavra GO), assim minimizamos o tráfego de rede durante a transação e reduzimos possíveis atrasos para completar a transação.

D) Use um nível de isolamento baixo: Determinar se a transação pode rodar em um nível de isolamento baixo. Implementando um nível de isolamento alto como o  "read commited", somente será permitido que a transação leia dados que não estão sendo alterados, ou seja, se estiver sendo efetuada alguma alteração,  a transação de leitura ficará bloqueada até que a alteração seja concluída. Um recurso muito utilizados pelos desenvolvedores é a utilização da HINT NOLOCK nos statements menos significativos.

Exemplo: SELECT au_lname FROM authors WITH (NOLOCK)

Links Relacionados:

KB832524: SQL Server technical bulletin - How to resolve a deadlock
Tips for Reducing SQL Server Deadlocks

Para saber mais sobre Hints no SQL Server, consulte por "locking, hints" no Books Online do SQL Server, ou abra o link mk:@MSITStore:C:Program%20FilesMicrosoft%20SQL%20Server80ToolsBooksacdata.chm::/ac_8_con_7a_1hf7.htm em uma máquina que tenha o BOL instalado.

 

Importancia de alinhar os discos para obter melhor performance com o SQL Server.

Antes de falar sobre a importância do alinhamento de discos, precisamos antes saber algumas nomenclaturas importantes.
Abaixo adicionei uma foto de um disco para podermos entender melhor.

Nomenclaturas:
Sectors: representa o menor pedaço de dados que pode ser lido ou escrito em um disco físico. A maioria dos discos possuem setores (sectors) de 512 bytes. Discos novos podem oferecer setores com tamanhos 1KB, 2KB, ou 4KB.
Clusters: são conhecidos por muitos como unidade de alocação de arquivo (file allocation unit). Seu tamanho é determinado quando a partição é formatada pelo Sistema Operacional. Cluster é definido por um grupo de setores (sectors) , seu tamannho ira depender do valor que foi definido para o file alocation unit. A maioria dos discos utilizam o tamanho de um setor de 512 bytes, considerando um file alocation unit de 64k então, 64K/512 bytes teremos 128 setores por cluster. Lembrando que Cluster = file alocation unit.
Track: cada lado de um disco (Platter) possui milhares de trilhas (tracks) onde são inseridos os setores (sectors) e por sua vez os clusters
Platters: são um ou mais pratos (Platters )de formato circular e de metal (quantidade depende do Hard Disk) onde são armazenadas as informações na superfície.
Stripe Unit Size: define o tamanho que os dados serão distribuídos entre os discos de um grupo RAID-0, RAID-10 ou RAID5.
Agora que entendemos as nomenclaturas podemos começar a falar sobre a importância de se alinhar um disco. O alinhamento de discos deve ser considerado para os volumes que são utilizados pelos arquivos de dados e transaction log do SQL Server.
Outra consideração importante é que o alinhamento deve ser considerado no Windows Server 2003 que não faz o alinhamento do disco por default. No Windows Server 2008 o alinhamento de discos é feito de forma automática, no entanto eu quero deixar um alerta devido ao que tenho visto em meus clientes aqui nos EUA que estão utilizando Windows Server 2008 e mesmo assim não estão com os discos alinhados. Em caso de migrações de Windows Server 2003 para Windows Server 2008, geralmente a storage é apresentada para o novo Sistema Operacional, no caso o Windows Server 2008, sem precisar redefinir os particionamentos. Mesmo sabendo que no Windows Server 2008 o alinhamento é feito por default, nesse caso não será feito porque as partições foram criados enquanto estavam no Windows Server 2003. O alinhamento é feito durante a criação da partição.
Para entendermos o porquê é necessário o alinhamento de um disco, devemos entender que todo disco usa algum espaço para armazenar informações sobre a partição, que então irão utilizar alguns setores ocultos (hidden sectors). Especialmente no Windows Server 2003 são reportados 63 setores ocultos por default. Considerando que cada setor possui 512 bytes então temos que 63 * 512 = 31.5 K que o disco ira utilizar para armazenar informações sobre a partição.
Tendo esse numero em mente vamos entender porque o disco fica desalinhado. Guarde bem em sua memória esses numeros.
Se você precisar consultar a nomenclatura acima novamente, sinta-se a vontade. Para refrescar a sua memória o Stripe Unit Size é determinado pela equipe de Storage no momento de criação das Luns, vamos considerar 64K para o nosso exemplo. Stripe Unit Size é o tamanho do “pedaço” de dados que será distribuído entre os discos de um Array da Storage.
Temos a seguinte configuração para usarmos como exemplo.
Stripe Size = 64K
Alocation Unit Size ou Cluster Size = 64K

Exemplo de um disco desalinhado.

No exemplo acima podemos ver uma situação de disco desalinhado, o Stripe Unit Size definido pela equipe de storage, possui um tamanho de 64k e esta representado na cor Azul na primeira linha da figura. O Stripe Unit Size define os limites fisicos de armazenamento para o Array.
Na segunda linha em amarelo podemos ver os setores que são utilizados para armazenar informações sobre a partição. Lembre-se que no Windows Server 2003 por default é utilizado 63 setores, considerando que o tamanho do setor é 512 bytes então teremos 31.5 K. Eu disse para você memorizar esse número. Repare que esse valor não preenche totalmente o tamanho definido pelo Stripe Unit Size que é 64K, deixando um espaço a ser preenchido. Então imagina o que irá acontecer quando os dados de usuário começar a ser gravado no disco.
Como exemplificado na linha 3 os dados de usuário, representado na cor verde, que nesse caso possui tamanho de alocação de 64K, definido pelo Alloc Unit Size, ira ser inserido entre dois espaços definidos no disco pelo Stripe Unit Size. Sempre que um dado de usuário ser inserido nos próximos espaços estará desalinhado em relação ao Stripe Unit Size definido para o Array.
Então como podemos resolver esse problema? Imagine se de alguma forma você reservasse um espaço para armazenamento de informações sobre a partição, onde o dado representado em amarelo preenchesse os 64K ao invés de 31.5K e então utilizar todo espaço definido pelo Stripe Unit no nosso exemplo a area em azul. Aconteceria que o próximo dado de usuário a ser inserido, representado em verde, iniciaria a partir do segundo Stripe Unit de 64K, evitando que a alocação feita pelo usuário não estaria entre dois espaços definidos pelo Stripe Unit. Consequentemente evitando o IO em dois lugares distintos onde precisaria apenas um.
Vamos ver agora como ficaria um exemplo utilizando um alinhamento onde reservaremos todo o espaço de 64K definido pelo Stripe Unit.

Nesse exemplo acima ao inves de usar o alinhamento default do Windows Server 2003 e utilizar apenas 31.5K, fizemos diferente e definimos o parametro align para 64K que esta representado em amarelo.
Isso irá preencher todo o espaço de 64K definido pelo parametro Stripe Unit, então as próximas alocações de dados de usuários, iniciara e terminara dentro do espaço definido pelo Stripe Unit.
Mesmo se for definido o Alloc Unit size/Cluster Size que é o bloco de dados gravado pelo usuário de 4K, estara ainda assim dentro do limite de 64K. Nesse caso serão necessarios 16 blocos de alocação de dados para preencher um Stripe Unite. Repare 16 * 4 = 64K portanto ainda estara alinhado.
Após entender essa teoria concluímos que o parâmetro Align dividido pelo Stripe Unit Size devera ser um numero inteiro sempre.
Como não se sabe a quantidade de espaço necessário para armazenar informações sobre a partição para os diferentes discos existentes no mercado, então a Microsoft recomenda utilizar o valor de alinhamento como 1024k ou 1MB.
Isso significa que assim como fizemos com 64k reservando espaço para dados de partição para garantir que os dados de usuário sejam gravados de acordo com o Stripe Unit, que nesse exemplo é 64K, podemos fazer o mesmo usando o valor 1024K recomendado pela Microsoft.
Se pegarmos o exemplo que usamos anteriormente usando um alinhamento de 64k ao invés de 31.5K (Windows Server 2003 Default) e um Stripe Unit Size de 64K temos o seguinte:
64K / 64K = 1 onde o resultado é igual a 1 bloco de Stripe Unit. Representado em amarelo, usamos 1 unidade para setores ocultos, para então iniciar a gravação dos usuários de acordo com os limites fisicos definidos pelo parametro Stripe Unit Size.
Podemos fazer o mesmo com o parametro de alinhamento 1024K e Stripe Unit Size de 64k
1024K / 64K = 16 o resultado aqui é também um numero inteiro, que significa que antes de iniciar a gravação de dados de usuários, iremos preencher 16 unidades de amarelo para setores ocultos, para então iniciar a gravação dos dados de usuário. Isso irá resultar que serão preenchidos 16 unidades de 64K para iniciar a gravação dos dados de usuário, que por sua vez estará alinhado com os limites fisicos definidos por Stripe Unit Size
Considerações
Align value : Stripe Unit Size deve ser um numero inteiro para que o disco grave de forma alinhada.
Allocation Unit Size que são blocos de dados de usuário, recomenda-se ser o mesmo valor de Stripe Unit Size.
Espero que tenham gostado do Post sobre alinhamento de discos e aguardo comentários caso tenham alguma dúvida. Em um outro post mostrarei como fazer o alinhamento de discos.
Para maiores informações e detalhes recomendo a leitura do Whitepaper Disk Partition Alignment Best Practices for SQL Server http://msdn.microsoft.com/en-us/library/dd758814(v=sql.100).aspx

Como utilizar o PERFORMANCE ANALYSIS of LOGS “PAL” para analizar falhas de performance

Uma grande ferramenta para analizar logs de contadores de performance é PAL. Através dessa ferramenta podemos gerar um relatório completo sobre os procesos em execução, utilização de CPU, utilização de Disco entre outros pontos importantes no troubleshooting de um caso de performance.
Antes de utilizar a ferramenta é necessário instalar a mesma. Para tal é necessário realizar o download e seguir os passos de instalação no endereço: http://pal.codeplex.com.
É importante observar os requisitos para a utilização PAL, entre eles a instalação dos software abaixo:
  • PowerShell v2.0 or greater
  • Microsoft .NET Framework 3.5 Service Pack 1
  • Microsoft Chart Controls for Microsoft .NET Framework 3.5
Após a instalação da ferramenta, podemos utilizar a própria para criar os contadores mais comuns e iniciar a coleta de dados.
Para fazer isso inicie a ferramenta e clique no botão "Threshold File":

Selecione em Threshold File Title qual o template você quer utilizar. Essa parte é importante pois existem templates específicos de acordo com a Role que é executada no servidor. Depois disso é só clicar em Export to Perfmon Template File:

Se abrirá uma janela para que você escolha em que local quer salvar o arquivo de template.

Agora basta abrir o performance monitor e importar um data collector, utilizando o arquivo XML exportado no passo anterior. Primeiro clicamos em New>Data Collector Set.

Clique em Create from a template (Recommended).

Clique em Browse e selecione o arquivo XML que você exportou anteriormente.

Clique em Finish.

Agora inicie o Data Collector para coletar os dados de performance:

Após a coleta dos dados de Performance clique com o botão direito em cima do Data Collector e então em STOP. Será gerado um arquivo com extensão BLG, este arquivo possui todos os dados capturados e iremos utiliza-lo para através do Performance Analysis of Logs ( PAL ) gerar um relatório amigável das informações de performance do equipamento.
Abra novamente o ( PAL ) e Clique em Next para ir para o próximo passo:

No passo Counter Log, você irá escolher qual o arquivo BLG você irá procesar, nesse caso vamos utilizar o arquivo BLG que acabamos de criar, para seleciona-lo basta clicar no botão que esta sinalizado na imagen abaixo.

Selecione o arquivo .BLG que foi criado anteriormente e clique em Next para avançar:

Na Aba Threshold File, clique em Next para avançar:

Na Aba Questions, responda as perguntas que irão ajudar a formular a análise que será realizada e clique em Next:

Em Output options mantenha o valor default e clique em Next:

Em File Output selecione onde será gravado o relatório e clique em Next:

Em Queue clique em Next:

Por final, clique em Finish:

Será aberta uma janela de prompt que executará o script "PAL".

Finalizado o script, o PAL criará um arquivo HTM na pasta que foi selecionada durante o assistente.

Nesse relatório, podemos observar diversos alertas, utilização de CPU, memoria, Disco, Rede entre outros. Todos esses gráficos são gerados com base nos dados coletados no momento em que o Data Collectors estaba em execução no equipamento. Portanto o recomendável é que o mesmo seja iniciado quando a falha de lentidão estiver ocorrendo. Sendo assim é possível através do relatório gerado pelo "PAL" observar qual é o dispositivo de hardware que está sob maior demanda naquele momento. Além disso com o relatório do "PAL" é possível identificar quais os procesos que estão sobrecarregando tal dispositivo de hardware. Por exemplo, em dos gráficos gerado pelo "PAL" é possível observar quantas requisições cada proceso está abrindo:

Essa dica se aplica aos sistemas operacionais:
  • Windows Server 2008
  • Windows Server 2008 R2
  • Windows Vista
  • Windows 7
Para utilizar o PAL no Windows Server 2003, basta utilizar o Perfwiz para criar os contadores e após criado o arquivo .blg utilizar o PAL para processar o arquivo e gerar os relatórios.