Instituto Superior
de
Engenharia do Porto
Engenharia Informática
Computadores e Sistemas
“Arquitectura de SQL Server
2000”
por
Pedro Miguel de Almeida Sousa
orientador
Eng. João Rocha
-2001-
Instituto Superior de Engenharia do Porto
TABELA DE CONTEÚDOS
Tabela de Conteúdos _________________________ ii
Lista de Figuras _____________________________ iv
Prefácio ___________________________________ 1
Agradecimentos _____________________________ 2
Introdução _________________________________ 3
1.
Capítulo ________________________________ 4
1.1) Evolução do Microsoft SQL Server: 1989 a 2000 4
1.1.1) O início do SQL Server _____________________ 4
1.1.2) O lançamento do SQL Server ________________ 6
1.1.3) O papel do OS/2 __________________________ 7
1.1.4) SQL Server 4.2 ___________________________ 8
1.1.4.1) Lançamento do OS/2 2.0 adiado____________ 8
1.1.4.2) Lançamento da versão 4.2 ________________ 8
1.1.5) SQL Server para NT _______________________ 9
1.1.6) O final do desenvolvimento conjunto _________ 11
1.1.7) SQL Server 95___________________________ 12
1.1.8) Nome de Código Sphinx ___________________ 12
1.1.9) Finalmente o SQL Server 2000 ______________ 14
2.
Capítulo _______________________________ 16
2.1) A Arquitectura do SQL Server 2000 ________ 16
2.1.1) O motor do SQL Server____________________ 16
2.1.2) O Net-Library ___________________________ 17
2.1.3) Open Data Services_______________________ 20
2.1.3.1) Buffers de input e output do ODS __________ 21
2.1.3.2) As Net-Libraries por defeito do ODS ________ 23
2.1.4) O Relational Engine e o Storage Engine _______ 24
2.1.4.1) O Parser de comandos __________________ 25
2.1.4.2) O Optimizer___________________________ 25
2.1.4.3) O SQL Manager ________________________ 26
2.1.4.4) O Expression Manager __________________ 27
2.1.4.5) O Query Executor ______________________ 28
2.1.4.6) Comunicações entre o relational engine e o
storage engine ____________________________________ 28
2.1.5) O Access Methods Manager_________________ 30
2.1.6) O Row Operations Manager e o Index Manager _ 30
2.1.6.1) O Row Operation Manager _______________ 31
2.1.6.2) O Index Manager ______________________ 32
2.1.7) O Page Manager e o Text Manager ___________ 35
2.1.8) O Transaction Manager ____________________ 36
Página ii
Instituto Superior de Engenharia do Porto
2.1.8.1) Uncommited Read______________________ 37
2.1.8.2) Commited Read _______________________ 38
2.1.8.3) Repeatable Read _______________________ 38
2.1.8.4) Serializable ___________________________ 39
2.1.9) O Lock Manager _________________________ 40
2.1.10) Outros Gestores ________________________ 41
2.2) A Gestão de Memória ___________________ 41
2.2.1) O Buffer Manager e Memory Pools ___________ 42
2.2.2) Acesso a In-Memory Pages _________________ 43
2.2.3) Acesso a Free Pages (Lazywriter) ____________ 43
2.2.3.1) Manter páginas em cache permanentemente _ 45
2.2.4) Checkpoints_____________________________ 45
2.2.5) Acesso a Páginas utilizando o Buffer Manager __ 47
2.2.6) Questões Relacionadas com Grandes Quantidades
de Memória 48
2.2.6.1) Read Ahead___________________________ 49
2.2.6.2) Merry-Go-Round Scans __________________ 50
2.2.6.3) O Log Manager ________________________ 51
2.3) Registo de Transacções e Recuperação _____ 52
2.3.1) Locking e Recuperação ____________________ 55
2.3.2) Páginas LSN e Recuperação ________________ 56
2.4) O Kernel do SQL Server e Interacção com o
Sistema Operativo ______________________________ 57
2.4.1) Threading e Multiprocessamento Simétrico_____ 58
2.4.2) O Worker Thread Pool _____________________ 60
2.4.3) E/S de Disco no Windows NT/2000 ___________ 62
3.
Conclusão ______________________________ 63
Bibliografia________________________________ 64
Página iii
Instituto Superior de Engenharia do Porto
LISTA DE FIGURAS
Figura 1: Esquema Geral da Arquitectura ____________________ 16
Figura 2: Arquitectura Net-Library do SQL Server 2000. ________ 19
Figura 3: Um Nonclustered Index com bookmarks no nível folha. _ 33
Figura 4: Um Clustered Index com os dados no nível folha. ______ 34
Figura 5: O Merry-Go-Round do SQL Server 2000 Enterprise Edition
____________________________________________________ 51
Figura 6: Três fases de recuperação do SQL Server ____________ 55
Figura 7: Comparação do LSN para verificar o processamento da
entrada do registo. _____________________________________ 57
Figura 8: Design de múltiplas threads num único processo do SQL
Server _______________________________________________ 60
Página iv
Instituto Superior de Engenharia do Porto
PREFÁCIO
Ao longo da minha vida profissional e de estudante, tive
contacto com vários sistemas SGBDR. No primeiro curso de
informática que fiz, aprendi a trabalhar com dBase e comecei a
compreender o modo de criação e estruturação de uma base de
dados. O raciocínio e planeamento de uma base de dados é algo que
obriga a um estudo profundo de um problema e constitui a base para
a implementação de uma boa solução.
Posteriormente, com o surgir do sistema operativo Windows,
comecei a trabalhar com Microsoft Access, mas, apesar das
diferenças para o dBase, ainda faltava algo.
A utilização do miniSQL no meu projecto de Bacharelato veio
acrescentar o SQL à minha lista de necessidades para um bom
SGBDR. Até que, na cadeira de Bases de Dados 2 leccionada pelo
Eng. Melo e Castro, conheci o SQL Server na sua versão 7 (beta).
Finalmente tinha conhecido uma base de dados que me
fornecia ferramentas e funcionalidades à medida do que eu esperava
de um bom sistema SGBDR.
Fui convidado, nesse mesmo ano, pelo Eng. Melo e Castro,
para trabalhar num projecto desenvolvido pelo IDT – Instituto para o
Desenvolvimento Tecnológico, tendo como base o SQL Server 6.5.
Foi nesse projecto que aprendi o que realmente é o SQL Server e a
gostar ainda mais da linguagem SQL.
No ano passado obtive uma bolsa de estudos para frequentar
os cursos do percurso oficial Microsoft com vista a atingir o grau de
Microsoft Certified Systems Engineering, que concluí com sucesso.
Actualmente lecciono cursos desse mesmo percurso na área de
Sistemas e pretendo obter as certificações em SQL Server 2000.
Como gosto de conhecer as tecnologias com que trabalho a fundo,
surgiu a ideia deste trabalho em “Arquitectura de SQL Server 2000”.
Página 1
Instituto Superior de Engenharia do Porto
AGRADECIMENTOS
Este projecto só foi possível com a ajuda do meu coordenador, o
Eng. João Rocha, que tenho o prazer de ter aceite o meu convite
para orientar pela segunda vez um trabalho meu. O facto de já nos
conhecermos há alguns anos fez com que o entendimento entre
ambos tenha sido mais fácil. Tenho a agradecer a liberdade de
escolha e decisão que me deu desde início, quer para a escolha do
tema, quer para a abordagem do mesmo.
Sem dúvida que o Eng. Melo e Castro teve também um papel
importante na escolha deste tema, uma vez que foi ele quem me
ensinou as bases para aquilo que sei hoje em dia sobre o SQL
Server.
Ao Eng. Alexandre Bragança, por me ter esclarecido algumas
dúvidas que tive ao longo do projecto.
E também à TecniData e ao coordenador de Formação, Nuno
Velho, pela ajuda a nível de recolha de informação e esclarecimento
de dúvidas e a disponibilidade de máquina para fazer testes e
experiências.
Página 2
Instituto Superior de Engenharia do Porto
INTRODUÇÃO
O objectivo deste trabalho é descrever quais os principais
componentes do SQL Server 2000, as suas funcionalidades e
interligação.
Não se pretende uma descrição pormenorizada das suas
ferramentas, nem da criação e manutenção de bases de dados, mas
sim do que está por trás de tudo isso.
Numa primeira fase teremos uma perspectiva histórica da
evolução do SQL Server até aos nossos dias. Segue-se uma
descrição dos seus componentes base e a sua interligação.
Página 3
Instituto Superior de Engenharia do Porto
1. Capítulo
1.1) EVOLUÇÃO DO MICROSOFT SQL SERVER: 1989 A
2000
Em 1985, a Microsoft e a IBM anunciaram um acordo de
desenvolvimento conjunto de longo termo de um sistema operativo e
outros produtos de software.
Este anuncio era o início do OS/2, o sucessor do sistema operativo
Microsoft MS-DOS. O OS/2 seria um sistema operativo mais
completo e robusto. Iria explorar os novos poderosos computadores
pessoais baseados no processador Intel 80286. E iria permitir
aplicações multitarefa, cada uma com o seu espaço de
endereçamento de memória e cada em execução no safe ring 3 do
esquema da Intel four-ring protection scheme do 80286.
O OS/2 foi formalmente anunciado em Abril de 1987, com
promessas de lançamento para o final desse mesmo ano (O OS/2
versão 1.0 foi lançado a 16 de Dezembro de 1987). Mas logo após a
declaração conjunta, a IBM anunciou uma versão especial do OS/2
denominada OS/2 Extended Edition. Esta versão mais poderosa iria
incluir de base o sistema operativo OS/2 mais um sistema SQL
SGBDR chamado OS/2 Database Manager. O OS/2 Database
Manager seria útil para pequenas aplicações e parcialmente
compatível com o DB/2 da IBM e com o menos utilizado SQL/DS.
1.1.1)
O início do SQL Server
Em 1986, a Microsoft era uma empresa “pequena” e os seus
produtos eram essencialmente focados em sistema desktop, sendo o
MS-DOS o seu principal produto. Aplicações cliente/servidor não
faziam parte do desenvolvimento da Microsoft. A gestão de dados
estava no seu início e a maioria das pessoas tinha os dados nos seus
PCs na folha de cálculo Lotus 1-2-3. O dBase da Ashton-Tate tinha
também começado a ser popular. Embora existissem outros
produtos, como o Paradox da Ansa Software, o dBase era claramente
líder nos produtos de gestão de dados em PCs. Em 1986, a Microsoft
não tinha nenhum produto de gestão de dados (Em 1992 atingiu um
grande sucesso com o Access e o FoxPro).
Página 4
Instituto Superior de Engenharia do Porto
A Microsoft virou-se para a Sybase como rampa de lançamento
para a entrada no mercado de SGBDs. A primeira versão do
DataServer ainda não tinha sido lançada, mas a sua pré-release
tinha obtido boa reputação por conter capacidades inovadoras, tais
como os stored procedures e triggers, e porque tinha sido
desenhada para um novo paradigma da computação: os ambientes
cliente/servidor.
Uma vez que a capacidade de processamento de transacções do
OS/2 não era esperada que fosse alta, a Sybase poderia utilizar o
sistema para preparar o mercado para futuras vendas dos sistemas
Unix mais poderosos. A Microsoft podia distribuir o produto em
volumes mais elevados do que a Sybase; simplesmente não era
economicamente possível para o grupo de vendas da Sybase
distribuir a primeira versão de uma base de dados aos utilizadores de
PCs. Este acordo foi assinado a 27 de Março de 1987 pelo presidente
da Microsoft Jon Shirley e pelo co-fundador e presidente da Sybase
Mark Hoffman.
No mundo das bases de dados em PCs, o dBase da Ashton-Tate
ainda tinha a reputação e grande fatia do mercado, apesar do dBase
e o DataServer da Sybase oferecerem capacidades extremamente
diferentes. Para ganhar aceitação, este novo e altamente capaz
SGBD da Microsoft (licenciado pela Sybase) necessitaria de agradar à
comunidade dBase. A melhor forma de o fazer era garantir o
patrocínio da Ashton-Tate e assim a Microsoft tratou de o conseguir.
Em 1988, um novo produto foi anunciado com o complicado nome
de Ashton-Tate/Microsoft SQL Server. Apesar de não fazer parte
do título do programa, a Sybase tinha um papel importante na
informação que acompanhava o produto. Este produto era uma porta
de entrada do DataServer no OS/2, comercializado por Ashton-Tate e
Microsoft. A Ashton-Tate prometeu que o seu produto dBase IV
também iria estar disponível numa edição servidor que iria utilizar as
ferramentas de desenvolvimento e linguagem do dBase IV como uma
plataforma cliente e que armazenaria os dados no novo SQL Server.
Esta nova característica cliente/servidor prometia dar ao dBase novos
níveis de poder que permitiriam suportar alguns utilizadores
concorrentes que poderiam ser suportados pela sua existente
arquitectura de ficheiros-partilhados.
A Ashton-Tate, a Microsoft e a Sybase trabalharam em conjunto
para lançar o SQL Server no OS/2 (Esta era a primeira vez que o
nome SQL Server era utilizado. Posteriormente a Sybase renomearia
o seu DataServer para Unix e VMS como Sybase SQL Server. Nos
nossos dias o servidor de base de dados da Sybase chama-se Sybase
Adaptive Server).
A primeira versão do beta do SQL Server da Microsoft e da
Ashton-Tate foi lançado no Outono de 1988.
Página 5
Instituto Superior de Engenharia do Porto
1.1.2)
O lançamento do SQL Server
Em 1990, o acordo de marketing e distribuição conjunta com a
Ashton-Tate, que pretendia ligar o SQL Server à grande comunidade
dBase, simplesmente não estava a funcionar. Até a versão desktop
do dBase IV estava bastante atrasada e tinha a reputação de conter
vários bugs quando lançada em 1989. A edição servidor, que iria
tornar mais simples desenvolver aplicações de alta-performance para
SQL Server utilizando dBase, não estava perto de estar pronta.
O desenvolvimento de aplicações mono-utilizador, orientadas a
registos é muito diferente de desenvolver aplicações para vários
utilizadores onde questões de concorrência, consistência e latência
de rede tem que ser consideradas. As primeiras tentativas de juntar
o SQL Server com as ferramentas do dBase não resultou, pois
tratava o SQL Server como se fosse utilizado um método de acesso
sequencial indexado (ISAM). Este tipo de acesso era o que os
utilizadores do dBase estavam habituados, mas não tirava partido da
potencialidades do SQL Server. Para se listar um conjunto de linhas
tinham que ser invocados comandos SQL para cada linha. O dBase
não tinha ainda a capacidade de saltar de registo para registo, saltar
registo para a frente ou para trás, etc. Ainda não existiam os
cursores (scrollable cursors).
Apenas dois anos antes, a Ashton-Tate era líder de mercado com
o seu produto, mas agora atravessava um mau período e tinha que
lutar pela sua sobrevivência. A Microsoft lançou o OS/2 LAN Manager
com o seu nome, e necessitava do SQL Server para criar uma base
de
ferramentas
de
desenvolvimento
em
arquitecturas
cliente/servidor. Assim a Microsoft e a Ashton-Tate terminaram a sua
parceria de distribuição e marketing. O SQL Server iria ser reempacotado e relançado como Microsoft SQL Server.
A versão 1.1 do Microsoft SQL Server foi lançado no Verão de
1990 como um upgrade da versão 1.0 da Asthon-Tate/Microsoft SQL
Server que havia sido lançada em 1989.
A versão 1.1 do SQL Server da Microsoft tinha as mesmas
características da versão 1.0, tendo no entanto várias correcções de
bugs. Mas a versão 1.1 também continha suporte para uma nova
plataforma cliente, o Windows 3.0 da Microsoft que havia sido
lançado em Maio de 1990. Este suporte para computadores a correr
Windows 3.0 foi uma das chaves do sucesso do SQL Server.
Página 6
Instituto Superior de Engenharia do Porto
1.1.3)
O papel do OS/2
Em 1991, a Microsoft lançou a versão 1.11, uma versão de
manutenção. A arquitectura cliente/servidor não estava ainda muito
desenvolvida, mas novos convertidos apareciam todos os dias. A
nível de vendas não era um grande sucesso, em parte devido ao
desapontamento com o OS/2. No entanto, o Windows 3.0 tinha sido
um grande sucesso e os utilizadores estavam a migrar de MS-DOS
para Windows 3.0, e não para OS/2.
Simultaneamente, a Microsoft estava a desenvolver uma versão
do SQL Server que servia para sincronizar com o novo produto da
Sybase para Unix, versão 4.2. Quando a versão 1.0 da Microsoft foi
lançada, o produto da Sybase era designado versão 3.0. Eles
acrescentaram algumas características necessárias para o mercado
de PCs, tais como tipos de dados de texto e imagem e modos de
visualização. A Sybase subsequentemente lançou a versão 4.0 para
várias plataformas, seguida da versão 4.2 num lançamento mais
limitado.
Entretanto, em Maio de 1991, a Microsoft e a IBM anunciaram o
fim da sua parceria de desenvolvimento do OS/2. A Microsoft decidiu
apostar e concentrar esforços nas novas versões do Windows e
aplicações para Windows. A Microsoft estava bem lançada no
desenvolvimento de um novo sistema operativo baseado num
microkernel denominado internamente como NT (“New Technology”).
Este novo sistema era para ser uma futura versão de OS/2 e foi
várias vezes denominado OS/2 versão 3.0. Depois da ruptura com a
IBM, o projecto NT foi alterado para integrar o interface do sistema
Windows e as APIs de programação Win32, e ficou conhecido como
Microsoft Windows NT.
A primeira versão do Windows NT só era esperada daí a dois anos.
O SQL Server seria eventualmente migrado para Windows NT. No
entanto, a Microsoft tinha que continuar o desenvolvimento do SQL
Server em OS/2, apesar de este agora ser um programa que
competia com a Microsoft.
Página 7
Instituto Superior de Engenharia do Porto
1.1.4)
SQL Server 4.2
A Microsoft estava a desenvolver o SQL Server 4.2 para o futuro
OS/2 2.0, a primeira versão de 32-bits do OS/2. Como o SQL Server
4.2 também estava desenhado para ser uma versão de 32-bits,
migrar o produto da versão de Unix seria mais fácil uma vez que a
segmentação de memória não seria um problema. Na teoria, o SQL
Server a 32-bits também seria mais rápido.
O principal ganho de performance esperado devia-se ao
endereçamento de memória. Uma vez que o endereçamento de
memória é tão comum, alguns cálculos rápidos mostravam que as
versões de 32-bits poderiam ter um aumento de performance de até
20% ou mais, mesmo que todas as outras operações se
mantivessem.
1.1.4.1) Lançamento do OS/2 2.0 adiado
A versão do OS/2 2.0 foi subitamente adiada no fim de 1991. De
facto, não havia a certeza se a IBM seria capaz de lançar o produto.
Assim, a Microsoft teve que migrar novamente o SQL Server para
16-bits e lançá-lo para OS/2 1.3.
Esta alteração custou à equipa de desenvolvimento da Microsoft 3
meses. No entanto, outro problema surgiu com o lançamento do
OS/2 1.3, uma vez que este só funcionava com máquinas IBM. Na
teoria, os fabricantes podiam licenciar uma versão do OS/2 OEM da
Microsoft e inclui-lo nos seus produtos, mas tal não aconteceu e os
pedidos de OS/2 desceram. Pela primeira vez, a Microsoft lançou um
produto denominado OS/2 versão 1.3, com o nome de código Tiger.
O Tiger incluía o SQL Server e o LAN Manager, minimizando o
problema do produto estar a ser lançado para um sistema operativo
morto.
1.1.4.2) Lançamento da versão 4.2
O SQL Server versão 4.2 entrou em fase beta no Outono de 1991,
e em Janeiro de 1992, o CEO da Microsoft, Bill Gates, anunciou
formalmente o produto numa conferência para programadores de
SQL Server em San Francisco. A versão 4.2 tinha sido na realidade
um esforço de desenvolvimento conjunto entre a Microsoft e a
Sybase. O motor da base de dados tinha sido migrado de Unix da
Página 8
Instituto Superior de Engenharia do Porto
versão 4.2, com os engenheiros da Microsoft e da Sybase a trabalhar
em conjunto na migração e correcção de erros. Adicionalmente, a
Microsoft ainda produziu bibliotecas para interface cliente de MSDOS, Windows e OS/2, e pela primeira vez incluiu uma ferramenta
de administração com um GUI Windows. O código fonte do motor da
base de dados foi adicionado nas instalações da Sybase, com
ficheiros a serem transferidos via modem e fitas magnéticas.
O SQL Server 4.2 foi lançado em Março de 1992. As críticas eram
boas e o feedback dos clientes era positivo.
Faltava o lançamento de uma versão de 32-bits do SQL Server.
1.1.5)
SQL Server para NT
O desenvolvimento de uma versão completa de 32-bits nunca foi
abandonado pela Microsoft.
Nos inícios de 1992, a equipa de desenvolvimento da Microsoft
tinha alguns problemas a resolver. Por um lado, tinha os seus
clientes baseados em OS/2, mas esses mesmos clientes tinham
deixado clara a necessidade de uma versão de 32-bits.
A ideia era claramente lançar uma versão para Windows NT, pois
esse sistema operativo representava o futuro. Seria a solução de
sistema operativo de grande porte da Microsoft, e de um ponto de
vista de desenvolvimento, apresentava uma série de vantagens
sobre o OS/2, incluindo I/O assíncrono, multiprocessamento
simétrico e portabilidade para arquitecturas RISC.
Embora a Microsoft tenha decidido em 1991 retornar a versões de
16-bits do SQL Server, o desenvolvimento de uma versão de 32-bits
não parou. Aquando do lançamento do OS/2 2.0, os testes das
versões de 16-bits e 32-bits do SQL Server não tinham a
performance esperada. Aliás a versão de 16-bits era mais rápida no
Tiger (OS/2 1.3)
Chegou-se a uma etapa em que o desenvolvimento de duas
versões, uma para OS/2 e outra para NT, complicava o
desenvolvimento. Em primeiro lugar, aumentar o número de pessoas
da equipa de desenvolvimento era uma má solução (normalmente
representava o problema e não a solução no desenvolvimento de
software). O desenvolvimento para os dois sistemas iria necessitar
da construção de um nível (camada) de abstracção, o que levaria
muito tempo de reengenharia do produto, além de que não se iria
tirar partido das características e potencialidades dos dois sistemas.
Assim foi decidido parar o desenvolvimento da versão para OS/2 e
concentrar os esforços de desenvolvimento para fazer evoluir a
versão para Windows NT.
Página 9
Instituto Superior de Engenharia do Porto
Por esta altura a Sybase estava a trabalhar numa nova versão do
seu produto, que iria receber o nome de System 10. Existia assim
uma agenda de prioridades diferentes entre a Microsoft e a Sybase.
Por um lado a Sybase necessitava do sucesso do seu novo System
10, a Microsoft apostava na migração do seu produto para NT o mais
rápido possível. Assim a Microsoft migrava o SQL Server de OS/2
para NT, ficando a Sybase com os clientes que pretendiam continuar
em OS/2 e a Sybase teria no NT um sistema operativo que seria dos
primeiros a suportar o System 10.
A equipa de desenvolvimento concentrou-se apenas na migração
para NT, tendo como um dos principais objectivos o seu lançamento
logo 90 dias após o lançamento de Windows NT. Não houve qualquer
preocupação em criar uma layer de abstracção, uma vez que só
desenvolviam para uma plataforma, o NT. O próprio sistema
operativo estava desenhado para ser portável, suportando diferentes
tipos de arquitecturas; ou seja, a layer de abstracção do SQL Server
seria o próprio NT.
O SQL Server estaria intimamente ligado ao NT a nível de gestão,
tal como o lançamento de eventos, a instalação baseada num serviço
e a exportação de estatísticas para o Performance Monitor do
Windows NT. A utilização de DLLs pelo NT, permitiu a criação de um
suporte que permitisse aos programadores a criação de aplicações
que estendessem as capacidades do SQL Server.
No final, esta nova versão do SQL Server acabou por ser mais do
que uma simples migração, uma vez que todo o kernel foi rescrito
para a API Win32.
Um outro objectivo era a capacidade de migração das versões de
OS/2 para esta nova versão e sistema operativo. Era necessário que
existisse uma forma de migração das aplicações SQL Server versão
4.2 para OS/2 sem alteração para a nova versão a correr em NT.
Uma das características do NT era a capacidade de dual-boot com
OS/2 ou MS-DOS. A nova versão do SQL Server tinha que permitir a
leitura e escrita de bases de dados directamente da versão OS/2.
As alterações foram efectuadas apenas no núcleo interno do SQL
Server, acrescentando novas características a nível de gestão,
suporte de rede e extensões, sem alterar o núcleo externo do motor
da base de dados o que iria comprometer a compatibilidade.
Em Julho de 1992, a Microsoft distribuiu numa conferência para
programadores sobre Windows NT uma versão pré-beta do Windows
NT e, apesar do SQL Server ainda não se encontrar em fase beta,
disponibilizou bibliotecas que permitissem ao programadores iniciar a
migração de OS/2 ou Windows 16-bits para NT. Para dar ênfase à
compatibilidade entre esta versão e a versão 4.2 baseada em OS/2,
a Microsoft designou esta nova versão como SQL Server 4.2.
Página 10
Instituto Superior de Engenharia do Porto
Em Outubro de 1992, a Microsoft lançou a primeira versão beta do
SQL Server para Windows NT. Esta versão beta apresentava quase
todas as características de um produto final e fornecia versões Win32
completas de todos os componentes. Foi lançada em 100 sites beta,
o que era algo sem precedentes para uma base de dados:
normalmente seriam aproximadamente 10.
Em Dezembro de 1993, quase todos os clientes baseados em
OS/2 tinham já migrado para esta nova versão e para o Windows NT.
Isto deveu-se não só ao facto da migração ser feita quase sem
problemas e sem alterações, mas principalmente porque
apresentavam um ganho de performance.
1.1.6)
O final do desenvolvimento conjunto
O sucesso da Microsoft levou a que as relações com a Sybase de
deteriorassem, uma vez que desde 1987 até 1993 muito havia
mudado a nível competitivo e de mercado. Ambas as empresas
haviam crescido imenso no mercado e as razões para o seu acordo
inicial tinham deixado de existir.
Também a equipa de desenvolvimento do SQL Server tinha
crescido ao longo dos anos, de um grupo de algumas pessoas para
mais de 50. Esta equipa tinha os conhecimentos e experiência de
desenvolvimento para Windows NT que era necessária para
desenvolver ainda mais o SQL Server, mas as condições do acordo
com a Sybase impediam que a Microsoft implementasse novas
características ou alterações sem o acordo da Sybase.
A Sybase tinha necessidades e prioridades diferentes das da
Microsoft, nomeadamente algumas novas características que se
poderiam implementar, tais como integração de messaging utilizando
MAPI e que não eram possíveis pois eram específicas dos sistemas
operativos da Microsoft.
As duas versões do SQL Server, para Windows NT da Microsoft e
para Unix/NetWare/VMS da Sybase estavam a competir no mesmo
mercado, levando a perda de clientes e vendas por parte da Sybase.
Como seria de esperar, a 12 de Abril de 1994 a Sybase e a
Microsoft anunciaram o fim do seu acordo. Cada empresa iria
desenvolver separadamente a sua versão do SQL Server. Estava
aberto o caminho para acrescentar novas características ao produto e
mudar o rumo do desenvolvimento. Ambas as versões teriam
compatibilidade com as versões anteriores, mas a partir deste ponto
o seu desenvolvimento divergiu e as novas versões apresentaram
características
diferentes.
Começavam
assim
a
competir
directamente uma com a outra.
Página 11
Instituto Superior de Engenharia do Porto
1.1.7)
SQL Server 95
No início de 1995, estava planeado que a nova versão do SQL
Server acrescentasse novas características do System 10, mas o fim
do acordo de desenvolvimento veio alterar este cenário. O
lançamento do System 10 no final desse ano fez com que a Microsoft
perdesse clientes.
Iniciava-se uma corrida para o lançamento de uma nova versão
com muitas características novas e melhorias a nível de performance.
Foi denominada SQL95 adoptando a designação da nova versão do
Windows a ser lançada por essa altura. Nesta altura o problema de
replicação estava na moda, tornando-se uma característica chave
desta versão. Os scrollable cursors, que se achava necessário incluir,
eram outra característica importante. Uma outra característica a ser
incluída passava por um novo sistema de gestão com o nome de
código StarFighter (conhecido hoje como SQL Server Enterprise
Manager) que também estava em desenvolvimento.
A primeira versão beta foi lançada nos finais de Outubro de 1994,
ainda com o StarFighter incompleto, mas com o motor da base de
dados final. A 14 de Junho de 1995, o produto final era lançado com
o nome de SQL Server 6.0.
Logo após o lançamento desta versão, começou o trabalho numa
nova versão que iria ser conhecida com SQL Server 6.5. Devido ao
lançamento de uma versão como a 6.0, cheia de novas
características, algumas funcionalidades foram adiadas e novas
necessidades surgiram. Por exemplo, a explosão da Internet e do
Data Warehousing. Estas características seriam incluídas no SQL
Server 6.5. A primeira versão beta foi lançada a 15 de Dezembro de
1995 e a versão final em Abril de 1996.
1.1.8)
Nome de Código Sphinx
Ainda antes do lançamento do SQL Server 6.5 uma equipa de
desenvolvimento já preparava separadamente o futuro. Em 1993, a
Microsoft havia decidido que as bases de dados eram uma área
chave e, em finais de 1994, começou a contratar profissionais da
DEC e de outras grandes companhias para trabalhar com as equipas
de desenvolvimento do Microsoft JET e do SQL Server numa nova
geração de tecnologias de bases de dados. Durante 1995, o período
de lançamento do SQL Server 6.0 e 6.5, esta equipa construiu um
novo motor de consultas (query processor) que daria origem ao
Microsoft Data Engine (MSDE).
Página 12
Instituto Superior de Engenharia do Porto
O desenvolvimento do MSDE foi complementado com o
desenvolvimento simultâneo do OLE BD, que permitiu que elementos
base do SQL Server fossem desenvolvidos como componentes
independentes. Estes componentes podiam assim comunicar
utilizando a layer de OLE BD. Nos finais de 1995, o novo componente
de processamento de consultas foi integrado no código base do SQL
Server e o desenvolvimento do novo SQL Server, denominado
Sphinx, começou.
O desenvolvimento desta nova versão tinha um objectivo
primordial: rescrever o motor da base de dados de forma a que o
SQL Server pudesse ser escalável até às necessidades dos
utilizadores. Isto significava capacidade para tirar partido de maior
quantidade e velocidade dos processadores e da memória que o
sistema operativo conseguisse suportar. Este crescimento implicava
a capacidade de suportar alterações aos seus componentes de uma
forma modular. Também seria alterado de forma a correr em
plataformas mais leves como desktops e portáteis.
Existiam dois objectivos principais:
•
Full row-level locking1 com um novo gestor de smart lock;
•
Um novo motor de processamento de queries que
permitisse tecnologias como processamento de queries
heterogéneas distribuídas e processamento eficiente de ad
hoc queries (necessário para a Internet e Data
Warehousing).
A versão beta 1 do SQL Server 7.0 foi lançada numa edição
limitada nos finais de 1997, sendo lançado em Dezembro de 1997 a
versão beta 2. Devido à nova arquitectura, todas as bases de dados
e estruturas de dados contidas tiveram que ser completamente
reconstruídas no processo de upgrade. Havia um compromisso com
os clientes de que as suas bases de dados seriam completamente
actualizáveis na migração da versão 6.5 para a versão 7.0. Foi
instituído um programa designado 1K Challenge, em que 1000
clientes foram convidados a enviar cópias das suas bases de dados
para a equipa de desenvolvimento para serem migradas para a
versão 7.0. Foi instalado um laboratório para efectuar estas
migrações e onde equipas de desenvolvimento convidadas
efectuaram testes de compatibilidade das suas aplicações com a
nova versão. Estes testes permitiram que a detecção e correcção de
problemas com a nova versão ainda antes dela ser lançada como
1
Mecanismo de bloqueio.
2
Comandos de interrogação à base de dados.
Página 13
Instituto Superior de Engenharia do Porto
produto final e a discussão de estratégias para tirar partido das
novas funcionalidades do produto.
Em Junho de 1998, foi lançada a versão beta 3 a partir do site
SQL Server Web, conjuntamente com exercícios que demonstravam
as novas características e capacidades do produto. A 16 de
Novembro de 1998, na COMDEX em Las Vegas foi publicamente
apresentado o novo produto, que seria lançado no mercado em
Janeiro de 1999.
1.1.9)
Finalmente o SQL Server 2000
Como seria de esperar, o desenvolvimento do SQL Server não
parou por aqui. Muitas características que não tinham sido incluídas
na versão 7.0 passariam a fazer parte da nova versão em
desenvolvimento. Nesta altura estavam planeado duas novas
versões, o Shiloh que seria uma actualização da versão 7.0 para 7.5
e o Yukon que seria a próxima grande versão a ser lançada.
As expectativas em relação ao Shiloh não eram muitas, uma vez
que era esperado que a maior parte dos clientes não instalassem
esta versão por a considerarem uma versão que necessitaria de
alguns service packs até atingir estabilidade.
No entanto, isto não se verificou. Na realidade o SQL Server 7.0
recebeu uma boa aceitação e a maior parte dos problemas pode ser
resolvido através de alguns Service Packs simples, não existindo
necessidade para uma versão .5.
Inclusive os clientes pediam novas características há muito
prometidas e sempre adiadas, como suporte para cascade deletes e
updates, melhorias a nível de partitioned views. Existia também um
desafio lançado pela Oracle Corporation que evidenciava
características que estavam incluídas no Oracle e não no SQL Server.
Assim foi decidido que a versão 7.5 seria não apenas uma
actualização da versão 7.0, mas uma nova versão completa,
acrescentando novas características. Com um período de
desenvolvimento de 18 meses, a objectivo inicial passava por
melhorias a nível de performance (o objectivo era um aumento de
pelo menos 20%). Uma vez que era um objectivo pouco concreto, a
equipa de desenvolvimento decidiu concretizar essa melhoria para o
processamento de queries do SAP R3, o que implicaria melhorias
também para muitas outras aplicações. Na apresentação do Windows
2000 em Fevereiro de 2000, San Francisco, foram anunciados os
resultados do teste efectuado com 6700 utilizadores no Sales and
Distribution benchmark do SAP R3 em comparação com o SQL Server
7.0 que apenas atingiu os 4500 utilizadores (testes realizado com o
Página 14
Instituto Superior de Engenharia do Porto
mesmo hardware, uma máquina com 8 processadores Pentium-III
550 MHz). Isto representava uma melhoria de 48%, superando os
objectivos iniciais.
Secretamente uma nova característica estava a ser acrescentada
ao SQL Server que não foi anunciada, nem incluída nas primeiras
versões beta. Só aquando do lançamento do Windows 2000 é que foi
revelado a inclusão de partitioned views no SQL Server e que tinham
permitido atingir as melhorias da performance anunciadas. Esta
característica foi denominada internamente por Coyote.
A versão Beta 1 do SQL Server foi lançada em Setembro de 1999
apenas para um grupo restrito de clientes e beta testers. Pouco
depois a Microsoft anunciava que o nome definitivo do produto seria
SQL Server 2000. Existiam duas razões para esta alteração de
nome. Em primeiro lugar, as características deste produto faziam
com que não fosse apenas uma versão intermédia, mas um produto
completamente novo. Em segundo lugar, se o produto adoptasse o
nome de versão 8.0, seria o único produto do BackOffice que não
utilizava o nome 2000. Para se enquadrar com os restantes produtos
da mesma linha foi decidido que adoptaria as mesmas linhas guia.
No entanto, internamente esta versão ainda utiliza o número
8.00.194 visível através da função @@VERSION.
Do ponto de vista do utilizador esta versão introduziu uma série
de novas funcionalidade, ainda mais do que a sua antecessora. A
versão 7.0 teve várias alterações, a rescrita do motor da base de
dados e outras alterações internas, mas a nível externo as alterações
ou novidades foram poucas. O SQL Server 2000 acrescentou novas
funcionalidades a nível de suporte multilíngue e alterações a objectos
tais como constraints de tabelas, vistas, triggers.
Devido às poucas alterações a nível do motor interno, foram
apenas previstas duas versões beta, sendo a Beta 2 lançada em Abril
de 2000. A 6 de Agosto de 2000, a equipa de desenvolvimento deu o
código por terminado e compilou a versão final, que entraria em
produção três dias mais tarde.
Se analisarmos a história deste produto vemos que ela passa por
uma série de alterações e acrescentar de características que os
utilizadores necessitam, sendo previsível que no futuro sejam
lançadas novas versões que devem estar hoje em desenvolvimento.
Página 15
Instituto Superior de Engenharia do Porto
2. Capítulo
2.1)
A ARQUITECTURA DO SQL SERVER 2000
Este capítulo pretende descrever quais os componentes da
arquitectura do motor do SQL Server 2000.
2.1.1)
O motor do SQL Server
A Figura 1 mostra um esquema geral da arquitectura. A partir
deste esquema serão descritos os vários componentes estudados
para este trabalho.
Figura 1: Esquema Geral da Arquitectura
Página 16
Instituto Superior de Engenharia do Porto
2.1.2)
O Net-Library
O Net-Library (frequentemente denominado Net-Lib) constitui um
nível (camada) de abstracção do SQL Server que lhe permite o
suporte de vários protocolos de comunicações de rede. Assim, a
forma de escrita e leitura de dados do SQL Server é feita através
desta camada que comunica com os protocolo utilizados através dos
drivers que os suportam. Esta implementação permite que os SQL
Server possa comunicar com vários tipos de protocolos, além de
possibilitar a alteração de suporte para novos protocolos ou
alterações aos já suportados.
A Net-Library é basicamente um driver para um mecanismo de
comunicação entre processos (interprocess communication – IPC).
Todo o código do SQL Server, inclusive o Net-Library, utiliza
chamadas ao subsistema Win32 da Microsoft. O SQL Server utiliza
um interface interno comum entre os Open Data Services (ODS) –
que fazem a gestão do utilização de rede – e cada driver da NetLibrary. Se existir necessidade de utilizar um protocolo de
comunicações completamente novo, o seu suporte em SQL Server
2000 passa pela criação de um simples driver Net-Library que o
suporte. Adicionalmente, podem ser chamados vários drivers NetLibrary simultaneamente, um para cada mecanismo IPC em uso.
O SQL Server constitui a camada de abstracção Net-Library em
ambas as máquinas (cliente e servidor), tornando possível o suporte
a vários clientes simultaneamente em redes diferentes. Os sistemas
operativos Windows, desde as versões NT/2000 ou 9x, suportam a
utilização de várias pilhas de protocolos simultaneamente; o NetLibrary baseia-se nos mesmos princípios. Existem dois aplicativos: o
Client Network Utility e o Server Network Utility que permitem
escolher e configurar o SQL Server.
O SQL Server 2000 tem duas bibliotecas principais de NetLibrary: Super Socket e Shared Memory. Além destas duas, existem
ainda bibliotecas consideradas secundárias que permitem o suporte a
TCP/IP, Named Pipes, IPX/SPX, etc. O OLE BD Provider para SQL
Server, o driver de ODBC do SQL Server, o DB-Library e o motor da
base de dados comunicam directamente com estas duas bibliotecas
principais. Comunicações entre dois computadores são efectuadas
pelo Super Socket, enquanto que comunicações locais, como por
exemplo entre uma aplicação e uma instância do SQL Server no
mesmo computador utilizam memória partilhada (Shared Memory suportado em todas as plataformas Windows).
Página 17
Instituto Superior de Engenharia do Porto
O Super Socket Net-Library é constituído por dois componentes:
•
Communication path Æ Se o cliente está configurado para
comunicar por TCP/IP Sockets ou NWLink IPX/SPX, o Super
Socket Net-Library chama directamente a API Windows
Socket 2 para o processo de comunicações entre a aplicação
e a instância do SQL Server.
Se o cliente estiver configurado para comunicar sobre
Named Pipes, Multiprotocol, AppleTalk ou conexão Banyan
Vines, um sub-componente do Super Socket Net-Library
chamado Net-Library router invoca a biblioteca secundária
necessária e reencaminha todos os pedidos para esta.
•
Encryption layer Æ A encriptação é implementada através
da API Secure Sockets Layer (SSL). O nível de encriptação,
de 40 bits ou 128 bits, depende da versão do Windows nos
computadores com a aplicação e o servidor de SQL. A
utilização de encriptação pode afectar a performance de
rede não só porque é necessário processamento adicional
para encriptar e desencriptar as comunicações mas também
devido ao tempo de retorno extra necessário entre o cliente
e o servidor sempre que uma conexão é efectuada.
As comunicações Shared
Memory
Net-Library são
inerentemente seguras sem a necessidade de encriptação. A
Shared
Memory
Net-Library
nunca
participa
em
comunicações entre computadores. A área de memória
partilhada entre processos de aplicações e o processo do
motor da base de dados não pode ser acedida por nenhum
outro processo do Windows.
Por questões de compatibilidade com versões anteriores do SQL
Server, a Multiprotocol Net-Library continua a suportar a sua própria
encriptação. Esta encriptação é especificada independentemente da
encriptação SSL e é implementada por chamadas à API de
encriptação Windows RPC.
A Figura 2 mostra a arquitectura do Net-Library do SQL Server
2000.
A distinção entre os mecanismos de IPC e os subsequentes
protocolos de rede é importante. Os mecanismos de IPC utilizados
pelo SQL Server incluem Named Pipes, RPC, SPX e Windows Sockets.
Os protocolos de rede utilizados incluem TCP/IP, NetBEUI, Shared
Memory, NWLink IPX/SPX, Banyan Vines SPP e AppletTalk ADSP.
Duas bibliotecas Net-Library, Multiprotocol e Named Pipes, podem
ser utilizadas simultaneamente sobre vários protocolos de rede
(NetBEUI, TCP/IP, NWLink IPX/SPX).
Página 18
Instituto Superior de Engenharia do Porto
Figura 2: Arquitectura Net-Library do SQL Server 2000.
O SQL Server 2000 sobre Windows NT/2000 suporta a
personificação de contextos de segurança para permitir autenticação
de acesso integrada chamada Windows Authentication operando
sobre os protocolos de rede que suportam autenticação entre cliente
e servidor. Este tipo de conexões são denominadas trusted
connections e são suportadas pelo SQL Server 2000 utilizando
qualquer Net-Library disponível. Em vez de necessitar de um
utilizador/password a cada ligação ao servidor, o SQL Server pode
personificar o contexto de segurança do utilizador a executar a
aplicação que efectua o pedido de conexão. Se esse utilizador tiver
privilégios suficientes (ou fizer parte de um grupo de utilizadores de
Página 19
Instituto Superior de Engenharia do Porto
Windows NT/2000 que tenha), a conexão é estabelecida. Esta
tecnologia não está disponível se o SQL Server estiver a ser utilizado
em Windows 98. Nesta situação é necessário especificar um
utilizador e uma password no próprio SQL Server.
2.1.3)
Open Data Services
Os Open Data Services (ODS) funcionam como o gestor de
clientes do SQL Server, constituindo basicamente um interface entre
as Net-Libraries do servidor e aplicações server-based, incluindo o
SQL Server. O ODS faz a gestão da rede: escuta pedidos de novas
conexões, termina conexões falhadas, confirma pedidos, coordena
serviços de threading do SQL Server e retorna resultados de pedidos,
mensagens, e valores de estado aos clientes.
Os clientes e servidores de SQL Server comunicam utilizando um
protocolo privado denominado Tabular Data Stream (TDS). O TDS
contém tokens que descrevem nomes de colunas, tipos de dados,
eventos e valores de estado na “conversa” entre cliente e servidor. O
servidor notifica o cliente que está a enviar um conjunto de
resultados (result set), indica o número de colunas e tipos de dados
dos resultados, etc. – tudo codificado em TDS. Nem cliente nem
servidor escrevem directamente para TDS. Em vez disso, os
interfaces OLE-DB, ODBC e DB-Library no cliente emitem em TDS
utilizando uma implementação cliente de Net-Library.
O ODS aceita novas conexões e se o cliente inesperadamente
desligar (por exemplo, se um utilizador fizer um reboot ao
computador em vez de terminar pacificamente a aplicação), o ODS
automaticamente liberta recursos como por exemplo os locks
(bloqueios) desse cliente.
O ODS pode ser utilizado para estender as funcionalidades do SQL
Server através de extended stored procedures. O código da API do
ODS estava anteriormente guardado externamente numa DLL
(opends60.dll). No SQL Server 2000, para melhorar o desempenho
dos mecanismos internos do SQL Server que necessitavam de
extended procedures pré-carregados, o código que constitui o ODS
está internamente no motor do SQL Server. DLLs com extended
stored procedures tem que incluir o opends60.dll, que contém stubs
para aceder às rotinas reais do ODS internamente no SQL Server.
3
Arquitectura baseada em duas camadas: servidor e cliente.
4
Programa baseado numa rotina pequena que substitui um programa mais
longo, possivelmente para ser carregado mais rápidamente ou remotamente. Por
exemplo, um programa que utilize RPC é compilado com stubs que substituem o
(continua)
Página 20
Instituto Superior de Engenharia do Porto
2.1.3.1) Buffers de input e output do ODS
Após o SQL Server colocar o conjunto de resultados num buffer de
output de rede (write buffer) que tem tamanho igual ao tamanho do
pacote do protocolo configurado, o Net-Library, é enviado para o
buffer do cliente. O primeiro pacote é enviado logo que o buffer
esteja cheio ou se um conjunto de resultados completo couber num
único pacote quando o batch tiver finalizado. Um batch é considerado
um conjunto de um ou mais comandos enviados ao SQL Server para
serem processados (parsed) e executados em conjunto. Por
exemplo, se estivermos a utilizar o OSLQ.EXE, um batch é a colecção
de todos os comandos que estão antes de uma instrução GO. Em
algumas operações excepcionais (como a que fornece informação de
progresso de um dump da base de dados ou mensagens DBCC), o
output buffer é enviado antes de estar completamente cheio ou a
operação de batch completa.
O SQL Server tem dois buffers de input (read buffers) e um buffer
de output por cliente. O double-buffering é necessário para as
leituras porque o SQL Server lê sequências (streams) de dados da
conexão do cliente e também tem que escutar por possíveis
mensagens (attention) do cliente. Mensagens deste tipo podem ser
interpretadas como dados “out-of-band”5, embora possam ser
enviados através de protocolos de rede que não tem explicitamente
um canal “out-of-band”. Foram efectuadas experiências, pela equipa
de desenvolvimento, de double-buffering e técnicas assíncronas para
os buffer de output mas não houve uma melhoria de performance
substancial. Apesar das escritas não serem assíncronas, o SQL
Server não necessita ultrapassar a cache do sistema operativo para
isso, tal como faz para escritas em disco.
Uma vez que o sistema operativo fornece cache para escritas na
rede, as acções de escrita parecem ser imediatas sem uma latência
significativa. Se, no entanto, são emitidas várias acções de escrita
para o mesmo cliente e o cliente não está a ler dados da rede, a
cache de rede ficará eventualmente cheia e as escritas bloqueiam.
Desde que a aplicação cliente esteja a processar resultados, o SQL
Server contém algumas filas de cache prontas para o processamento
programa que requer um procedimento remoto. O stub aceita o pedido e depois
reenvia-o (através de outto programa) para o procedimento remoto. Quando esse
procedimento acabar o seu serviço, retorna o resultado ou outro estado ao stub
que o passa ao programa que fez o pedido.
5
Canal lógico de transmissão independente associado a cada par de sockets
conectados. Utilizado para transmissão de dados de controlo.
Página 21
Instituto Superior de Engenharia do Porto
da conexão do cliente. Mas se a fila do cliente está cheia com
resultados e o cliente não os processa, o SQL Server deixa de os
enviar e as escritas de rede para esse cliente tem que esperar. Uma
vez que o SQL Server tem apenas um buffer de output por cliente, os
dados não podem ser enviados para a conexão desse cliente
enquanto ele não ler a informação da rede de forma a libertar espaço
para que a operação de escrita possa finalizar (as acções de escrita
para os restantes clientes não são afectadas por este bloqueio).
Escritas para a rede bloqueadas podem também afectar os locks.
Por exemplo, se READ COMMITTED está a ser utilizado (opção por
defeito), um lock partilhado pode normalmente ser libertado depois
do SQL Server ter completado o page scan6. (Locks exclusivos
utilizados para modificar dados tem que ser sempre mantidos até ao
fim da transacção para garantir a possibilidade de rollback da
transacção). No entanto, se a busca encontrar mais dados relativos e
o output buffer não estiver livre, o scan vai bloquear. Quando a
escrita para a rede anterior acabar, o output buffer fica livre e o scan
pode continuar.
Se uma conexão de um cliente demorar o processamento de
resultados que lhe são destinados, podem existir problemas de
concorrência porque os locks são mantidos mais tempo do que
contrariamente seriam. Ocorre uma espécie de acção em cadeia - se
o cliente não leu uma série de pacotes de rede, posteriores escritas
do output buffer do lado do servidor de SQL têm que esperar porque
a fila está cheia. Uma vez que o output buffer não está disponível, o
scan por dados pode também ser suspenso por que não existe
espaço para adicionar os resultados. Uma vez que o scan foi
suspenso, qualquer lock nos dados não pode ser libertado. Em
resumo, se uma aplicação cliente não processar convenientemente e
atempadamente os resultados, a concorrência na base de dados
pode ser afectada.
O tamanho do output buffer também pode afectar a velocidade a
que os clientes recebem o primeiro conjunto de resultados. Como foi
mencionado anteriormente, o output buffer é enviado quando o
batch ( e não simplesmente o comando) acabar, ainda que o buffer
não esteja cheio. Se existem duas consultas no mesmo batch e a
primeira apenas tem um conjunto de dados pequeno, os seus
resultados não são enviados para o cliente até que a segunda
consulta acabe ou forneça dados suficientes para encher o buffer. Se
ambas as consultas se processarem rapidamente, esperar pelos
resultados não é problemático. Mas suponhamos que a primeira
consulta é rápida e a segunda não. Adicionalmente suponhamos que
6
Consulta de dados, sem utilização de índices, numa página que implica
uma passagem completa por toda a página.
Página 22
Instituto Superior de Engenharia do Porto
a primeira consulta retorna 1000 bytes de dados. Se o tamanho do
pacote de rede for 4096 bytes, os resultados da primeira consulta
tem que aguardar que os resultados da segunda consulta o encham.
A solução óbvia aqui seria colocar o primeiro comando no seu próprio
batch ou diminuir o tamanho do pacote de rede. A primeira solução
parece o ideal, uma vez que é difícil afinar uma aplicação para
determinar qual o tamanho ideal de pacote para cada comando.
Claro que isto não significa que cada comando deva correr no seu
próprio batch, muito pelo contrário. Em circunstâncias normais, o
agrupamento de múltiplos comandos num único batch é mais
eficiente e recomendável porque reduz o número de handshakes
entre cliente e servidor.
2.1.3.2) As Net-Libraries por defeito do ODS
No lado do servidor, e ODS espelha as funções do ODBC, OLE DB
ou DB-Library no cliente. As chamadas a uma aplicação servidor ODS
permitem descrever e enviar conjuntos de resultados, converter
valores entre tipos de dados, controlar o contexto de segurança
associado com uma conexão específica a ser gerida e lançar eventos
de erro e mensagens às aplicações cliente.
O ODS utiliza um modelo de programação orientada a eventos.
Pedidos de servidores e dos clientes disparam eventos a que o
servidor deve responder. Utilizando a API do ODS, podem ser criadas
rotinas personalizadas, chamadas event handler, para cada tipo
possível de evento. Essencialmente, o ODS conduz a aplicação
servidora invocando os seus event handlers personalizados como
resposta aos pedidos dos clientes.
As aplicações do servidor ODS respondem aos seguintes eventos:
•
Eventos de conexão Æ Quando uma conexão ocorre, o
SQL Server inicializa uma verificação de segurança para
determinar se a conexão é permitida. Outras aplicações
ODS, tais como o gateway do DB/2, têm os seus próprios
handlers de validação (logon) que determinam se as
conexões são permitidas.
•
Eventos de linguagem Æ Quando um cliente envia um
comando, tal como uma instrução SQL, o SQL Server passa
este comando para o parser. Uma aplicação ODS diferente,
7
Estabelecimento de um acordo entre as partes envolvidas numa
comunicação ou transacção de dados. Neste acordo, são estabelecidos parâmetros
de comunicação, tais como: velocidade de transmissão, tamanho do pacote
(trama), etc.
Página 23
Instituto Superior de Engenharia do Porto
tal como um gateway, iria instalar o seu próprio handler que
aceitaria e executaria o comando.
•
Eventos de RPC (Remote Procedure Call) Æ Estes eventos
ocorrem de cada vez que um cliente ou servidor SQL Server
dirige um pedido de processamento remoto ao ODS.
O ODS também gera eventos relacionados com certas actividades
dos clientes e das aplicações. Estes eventos permitem a uma
aplicação servidor de ODS responder a alterações ao estado da
conexão do cliente ou do servidor ODS.
Adicionalmente ao controlo de conexões, o ODS faz a gestão de
processos (threads) e fibers para o SQL Server (o SQL Server deixa o
sistema operativo fazer a gestão das threads no sistema. No entanto,
em situações extremas de sobrecarga do processador, o SQL Server
pode assumir esse papel baixando o nível de processamento para um
nível mais próximo do micro-kernel e utilizando processos mais
pequenos denominados fibers). Toma conta da criação e terminação
de processos e disponibiliza o processo para o User Mode Scheduler
(UMS). Uma vez que o ODS é um interface aberto com uma API de
programação completa e um conjunto de ferramentas, a escrita de
aplicações servidor com ODS tem os mesmo benefícios que o SQL
Server deste componente, incluindo gestão e pooling de processos
com SMP, assim como gestão de rede para múltiplas redes
simultâneas. Esta operação multithread8 permite à aplicação servidor
de ODS manter um nível alto de performance e disponibilidade e
utilizar múltiplos processadores de uma forma transparente sobre
Windows NT/2000 uma vez que o sistema operativo consegue
escalonar qualquer processo em qualquer processador disponível.
2.1.4)
O Relational Engine e o Storage Engine
O motor da base de dados do SQL Server é composto por dois
componentes, o relational engine e o storage engine. Estes dois
componentes estão claramente separados e o seu método primário
de comunicações é através do OLE BD. O relational engine contém
todos os componentes necessários para parsing e optimização de
queries. Também é responsável por gerir a execução de queries
enquanto estas solicitam os dados do storage engine em termos de
conjuntos de registos (row set) OLE BD e posterior processamento
de resultados. O storage engine compreende os componentes
necessários ao acesso e modificação de dados em disco.
8
Operação executada em múltiplos processos.
Página 24
Instituto Superior de Engenharia do Porto
2.1.4.1) O Parser de comandos
O parser de comandos controla eventos de linguagem do ODS.
Verifica a sintaxe correcta e traduz os comandos Transact-SQL num
formato interno que pode ser executado. Este formato interno é
conhecido como uma árvore de pesquisa (query tree). Se o
parser não reconhecer a sintaxe, um erro de sintaxe é lançado e
identifica onde o erro ocorreu. No entanto, mensagens de erro sem
ser de sintaxe não podem explícitas sobre o local exacto no código
fonte da linha que causou erro. Uma vez que apenas o parser pode
aceder ao código fonte de um comando, o comando não está
disponível em formato fonte quando é executado.
2.1.4.2) O Optimizer
O optimizer retira a árvore de execução do parser e prepara-a
para execução. Este módulo compila um batch inteiro, optimiza as
queries e verifica a segurança. A optimização e compilação resultam
num plano de execução.
O primeiro passo na criação de um plano deste tipo é a
normalização de cada query o que normalmente resulta na divisão
de uma query em várias mais pequenas. Após o optimizer normalizar
a query, optimiza-a, o que significa que o optimizer determina um
plano de execução para essa query. A optimização de queries é
baseada em custos; o optimizer escolhe o plano com menor custo
baseado em métricas internas que incluem requisitos de memória,
utilização estimada da CPU e número de pedidos de I/O previstos. O
optimizer considera o tipo de pedido, verifica o tamanho dos dados
nas várias tabelas afectadas, verifica os índices para cada uma das
tabelas e depois efectua uma amostragem de dados mantida para
cada índice ou coluna referenciada pela query. A amostragem de
dados é designada por distribution statistics. Baseado na informação
disponível, o optimizer considera os vários métodos de acesso e
estratégias de join que pode utilizar para executar a query e escolhe
o de menor custo. O optimizer também decide quais os índices, se
algum, a serem utilizados para cada tabela afectada e, no caso de
uma multitable query, a ordem em que devem ser acedidas e qual a
estratégia de join.
O optimizer utiliza heurísticas de “corte” (pruning) para garantir
que não é despendido mais tempo a optimizar uma query do que
simplesmente escolhendo um plano e executá-la. O optimizer não faz
necessariamente uma optimização exaustiva.
Página 25
Instituto Superior de Engenharia do Porto
Após a finalização da normalização e optimização, a árvore
normalizada produzida é compilada num plano de execução que
constitui, na realidade, uma estrutura de dados. Cada comando
incluído especifica exactamente qual a tabela afectada, que índices
vão ser utilizados (se algum), que verificações de segurança tem que
ser feitas e quais os critérios (condições de pesquisa) que devem ser
classificados como TRUE. Este plano de execução pode ser
consideravelmente
mais
complexo
do
que
é
aparente.
Adicionalmente aos comandos, o plano de execução inclui todos os
passos necessários para garantir que as restrições (constraints) são
verificadas. Os passos para chamar um trigger são um pouco
diferentes dos necessários para verificar uma restrição. Se um
trigger é incluído nas acções a serem efectuadas, a chamada ao
procedimento que inclui o trigger é adicionado. Se o trigger é do tipo
instead-of trigger, a chamada ao trigger pode substituir o próprio
comando de modificação de dados. Para after triggers10, o plano do
trigger é ramificado após o plano de execução do comando de
modificação que disparou o trigger, antes que essa modificação faça
COMMIT. Os passos específicos do trigger não são compilados no
plano de execução, ao contrário dos de verificação de uma restrição
(constraint).
O simples pedido de inserção de uma linha numa tabela com
várias restrições pode resultar num plano de execução que necessite
que várias outras tabelas também sejam acedidas ou que expressões
sejam avaliadas. A existência de um trigger também pode provocar
que muitos outros passos sejam executados. O passo que executa
realmente o comando de inserção pode ser uma pequena parte do
plano de execução total necessário para garantir que todas as acções
e verificações de restrições associadas à inserção de uma linha sejam
cumpridas.
2.1.4.3) O SQL Manager
O SQL Manager é responsável por todas as acções que se
relacionam com a gestão de stored procedures e com os seus planos
de execução. Determina quando um stored procedure necessita de
9
Este tipo de trigger constitui uma das novidades do SQL Server 2000. Um
trigger é constituído por comandos SQL que executados mediante disparos de
eventos sobre tabelas. Este novo tipo, acrescenta a característica de substituir as
acções que dispararam o trigger.
10
Triggers executados após a execução dos comandos que dispararam o
trigger.
Página 26
Instituto Superior de Engenharia do Porto
ser recompilado baseado em mudanças no schema11 de objectos e
gere a cache dos planos de execução de forma a que outros
processos os possam utilizar.
O SQL Manager também controla a autoparametrização de
queries. No SQL Server 2000, certo tipo de ad hoc queries12 são
tratadas como se fossem stored procedures parametrizados e os
planos de execução são criados e guardados para tal. Isto pode
acontecer se uma query utiliza uma simples comparação de
igualdade de uma constante, como o exemplo seguinte:
SELECT * FROM pubs.dbo.titles
WHERE type = ‘business’
Esta query pode ser parametrizada como se fosse um stored
procedure com um parâmetro para o valor de type:
SELECT * FROM pubs.dbo.titles
WHERE type = @param
Uma outra query pode, diferindo apenas no valor de type, utilizar
o plano de execução que foi gerado para a query original.
2.1.4.4) O Expression Manager
O Expression Manager controla a computação13, comparação e
movimentação de dados. Suponhamos que uma query contém algo
do género:
SELECT @myqty = qty * 10 FROM mytable
11
Numa comparação com a normal SQL92, o schema é o equivalente á
informação sobre base de dados.
12
Uma ad hoc querie é considerada como uma consulta de dados sobre
múltiplas fontes de dados com uma periodicidade muito baixa.
13
Dados obtidos através de cálculos. Por exemplo, uma coluna de uma
tabela obtida em função de uma operação aritmética sobre outras colunas.
Página 27
Instituto Superior de Engenharia do Porto
O Expression Manager copia o valor de qty do row set14 retornado
pelo storage engine, multiplica-o por 10 e guarda o resultado em
@myqty.
2.1.4.5) O Query Executor
O Query Executor executa o plano de execução que o Optimizer
criou, funcionando como um intermediário para todos os comandos
na execução do plano. Este módulo passa por cada passo de cada
comando do plano de execução até o batch ter terminado. A maioria
dos comandos necessita de interacção com o storage engine para
modificar ou obter dados e para gerir transacções e locking.
2.1.4.6) Comunicações entre o relational engine e o
storage engine
O motor relacional utiliza OLE DB para a maior parte das
comunicações com o motor de armazenamento. A descrição seguinte
é uma adaptação da secção intitulada “Database Engine Concepts”
do SQL Server Books Online. Descreve como uma instrução SELECT
que processa dados apenas de tabela locais é processada:
1. O motor relacional compila a instrução SELECT num plano
de execução optimizado. O plano de execução define um
conjunto de operações sobre conjuntos simples de row sets
OLE BD de tabelas individuais ou índices referenciados na
instrução SELECT. O row set requisitado pelo motor
relacional retorna o conjunto de dados necessário da tabela
ou índice para executar uma das operações utilizadas para
construir o conjunto de resultados da instrução. Por
exemplo, esta instrução SELECT necessita de um table scan
se referencia uma tabela sem índices.
SELECT * FROM Northwind.dbo.ScanTable
14
Um row set corresponde a um conjunto de registo obtidos através de
uma consulta à base de dados. Este termo, normalmente, é utilizado para designar
o conjunto de dados retornado ao cliente que efectuou a pesquisa.
Página 28
Instituto Superior de Engenharia do Porto
O motor relacional implementa o index scan através de um
pedido de um row set contendo todos os registos de
ScanTable. Esta próxima instrução SELECT necessita
apenas informação contida num índice:
SELECT DISTINCT LastName
FROM Northwind.dbo.Employees
O motor relacional implementa o index scan pedindo um
row sets que contém as folhas (leaf level rows) do índice
que foi construído sobre a coluna LastName. A próxima
instrução necessita de informação a partir de dois índices:
SELECT CompanyName, OrderID, ShippedDate
FROM Northwind.dbo.Customers As Cst
JOIN Northwind.dbo.Orders As Ord
ON ( Cst.CustomerID = Ord.CustomerID )
O motor relacional pede dois row sets: um para o índice
nonclustered em Customers e o outro para um índice
clustered de Orders.
2. O motor relacional utiliza a API OLE DB para pedir ao motor
de armazenamento acesso aos row sets.
3. Enquanto o motor relacional processa os vários passos do
plano de execução e necessita de dados, utiliza OLE DB para
ler os registos do row set que pediu ao motor de
armazenamento para abrir. O motor de armazenamento
transfere os dados dos buffers de dados para o motor
relacional.
4. O motor relacional combina os dados dos rows sets
recebidos do motor de armazenamento com o result set
final transmitido para o utilizador.
Nem todas as comunicações entre o motor relacional e o de
armazenamento utilizam OLE DB. Alguns comandos não podem ser
explicitados em termos de row sets de OLE DB. O melhor e mais
explícito exemplo é quando o motor relacional processa comandos de
data definition language (DDL) para criar uma tabela ou outro
objecto do SQL Server.
Página 29
Instituto Superior de Engenharia do Porto
2.1.5)
O Access Methods Manager
Quando o SQL Server necessita de localizar dados, invoca o gestor
de métodos de acesso (Access Methods Manager). Este gestor
prepara e executa scans em data pages e index pages e prepara os
row sets de OLE DB para retornarem dados ao motor relacional.
Contém serviços para aceder à tabela, buscar os dados qualificados15
e actualizar dados. Este gestor não lê na realidade as páginas; faz
apenas o pedido ao gestor de buffer, que em última instância serve a
página da sua cache ou a lê do disco para cache. Quando é iniciado o
scan, um mecanismo de look-ahead qualifica os registos ou índices
na página. A leitura dos registos que se enquadram no critério
especificado é designada como qualified retrieval. O gestor de
métodos de acesso é utilizado não só nas consultas (queries) mas
também em updates ou deletes qualificados (por exemplo, uma
instrução UPDATE com uma clausula WHERE).
Uma sessão abre uma tabela, requisita e avalia um conjunto de
registos contra as condições na clausula WHERE e, depois, fecha a
tabela. Um session descriptor data structure (SDES) mantém um
registo da linha corrente e das condições de pesquisa para o objecto
a ser operado (que é identificado por um object descriptor data
structure ou DES).
2.1.6)
O Row Operations Manager e o Index
Manager
Podemos considerar este dois gestores como parte integrante do
gestor de métodos de acesso (access methods manager) uma vez
que eles implementam, na realidade, o método de acesso. Cada um
é responsável por manipular e gerir as suas estruturas de dados em
disco, nomeadamente registos de dados e índices B-Tree (o SQL
Server utiliza uma implementação de B-Tree denominada B-Tree*).
Eles compreendem e manipulam a informação nas páginas.
15
Dados que estão dentro dos critérios de selecção da instrução SQL. Por
exemplo, numa instrução SELECT com uma cláusula WHERE, os dados qualificados
seriam aqueles que estivessem dentro do critério definido na cláusula WHERE.
Página 30
Instituto Superior de Engenharia do Porto
2.1.6.1) O Row Operation Manager
O row operation manager lê, modifica e executa acções em
registos individuais. Ele executa uma operação dentro de um registo,
tal como “ler o campo 2” ou “escrever este valor no campo 3”. Como
resultado do trabalho executado pelo gestor de métodos de acesso,
pelo gestor de locks e pelo gestor de transacções, o registo será
encontrado e será devidamente bloqueado e considerado parte da
transacção. Após formatar ou modificar o registo em memória, esta
acção insere ou apaga o registo.
Este gestor também controla as alterações. O SQL Server 2000
fornece três métodos para alteração de dados. Todos são directos, o
que significa que não há necessidade de duas passagens pelo registo
de transacções (transaction log), como acontecia com os deferred
updates16 nas versões anteriores ao SQL Server 7. O SQL Server
2000 desconhece o conceito de uma operação de deferred update.
O SQL Server 2000 tem três métodos de alteração:
•
In-place mode Æ Este método é utilizado para actualizar
uma heap ou clustered index quando nenhuma chave de
clustering é modificada. A actualização pode ser executada
localmente, e os novos dados são escritos no slot na página
de dados.
•
Split mode Æ Este método é utilizado para actualizar
nonunique indexes quando as chaves do índice são
alteradas. A alteração é separada em duas operações – uma
eliminação seguida de uma inserção – e estas operações são
executadas independentemente uma da outra.
•
Split with collapse mode Æ Este método é utilizado para
alterar um unique index quando as chaves do índice são
alteradas. Após a alteração ser re-escrita como operações
de eliminação e inserção, se a mesma chave é eliminada e
posteriormente inserida com um novo valor, a eliminação e
inserção é “condensada” numa só operação.
16
Actualizações de dados adiadas.
Página 31
Instituto Superior de Engenharia do Porto
2.1.6.2) O Index Manager
O index manager mantém e dá suporte a pesquisas em B-Trees,
que são utilizadas para os índices do SQL Server. Um índice é uma
estrutura em árvore, com uma página raiz, páginas de níveis
intermédios e folha. Uma B-Tree agrupa registos com um índice
semelhante, permitindo assim um acesso aos dados mais rápido
através de pesquisa sobre um valor chave. O princípio de uma BTree é o balanceamento da árvore (o B significa Balanced). Os ramos
da árvore de índices são juntos ou separados quando necessário de
forma a que a pesquisa por um registo atravesse sempre o mesmo
número de níveis e assim necessite do mesmo número acessos a
páginas.
A travessia é iniciada na raiz, progredindo para níveis intermédios
e, finalmente, para páginas de níveis inferiores denominadas páginas
folha. Numa pesquisa qualificada ou numa eliminação, a folha
correcta é a página mais baixa da árvore onde um ou mais registos
com a chave ou chaves especificadas reside. O SQL Server suporta
tanto clustered como nonclustered indexes. Num nonclustered index
(Figura 3), o nível folha da árvore contém todos os valores chave do
índice em conjunto com um bookmark para cada valor da chave. O
bookmark indica onde se encontram os dados referenciados e pode
assumir de duas formas, dependendo se as tabelas base tem um
clustered index. Se a tabela base não contém um clustered index, a
tabela é referenciada como sendo uma heap. O bookmark em
páginas folha de um nonclustered index para um heap são ponteiros
(apontadores) para registos onde podem ser encontrados os dados.
Estes ponteiros consistem num ID de linha (RID), que é um número
de ficheiro, num número de página e num número de linha nessa
página. Se a tabela base tem um clustered index, o bookmark em
páginas folha de um nonclustered index contém os valores da chave
do clustered index para o registo.
Após atingir o nível folha num nonclustered index, podemos
encontrar a localização exacta dos dados, apesar de ainda termos
que obter separadamente a página onde os dados se encontram.
Uma vez que se pode aceder directamente aos dados, não é
necessário percorrer todas as páginas de dados para encontrar um
registo qualificado. Num clustered index (Figura 4), o nível folha
contém na realidade todos os dados, não simplesmente valores
chave. Um clustered index mantém os dados numa tabela ordenada
logicamente pela chave do clustered index e as páginas folha são de
facto as páginas de dados da tabela. Todas as páginas de dados com
um clustered index estão ligadas por listas duplamente ligadas.
Página 32
Instituto Superior de Engenharia do Porto
Seguindo as páginas, e as linhas dessas páginas, desde a primeira
página até à última obtém-se a ordem lógica dos dados.
Um vez que os dados apenas podem ser ordenados uma vez, só
um clustered index pode existir por tabela. Isto faz com que a
escolha da chave do índice seja um aspecto importante nas
considerações de desempenho.
Também se podem utilizar índices para garantir a unicidade do
valor de uma chave específica. De facto, as cláusulas PRIMARY KEY e
UNIQUE de uma coluna, funcionam pela criação de um índice único
sobre os valores dessa coluna. O optimizer pode utilizar o
conhecimento sobre a unicidade de índice para a formulação de um
plano de execução efectivo. Internamente, o SQL Server garante
sempre que os cluster indexes são únicos pela adição de um
uniqueifier de 4 bytes aos valores da chave do clustered index que
ocorrem mais do que uma vez. Este valor torna-se parte da chave e
é utilizado em todos os níveis do clustered index e referencia a chave
do clustered index em todos os nonclustered indexes.
Figura 3: Um Nonclustered Index com bookmarks no nível folha.
Página 33
Instituto Superior de Engenharia do Porto
Um vez que o SQL Server mantém uma ordenação em índices no
nível folha, não é necessário descarregar e recarregar os dados para
manter as propriedades de clustering quando dados são
acrescentados ou movidos. O SQL Server adiciona sempre linhas nas
páginas correctas numa sequência de cluster. Para um clustered
index, a página folha correcta é a página de dados onde uma linha de
dados é inserida. Para um nonclustered index, a página folha
correcta é aquela onde o SQL Server insere a linha contendo o valor
chave (e bookmark) para a nova linha inserida. Se os dados são
alterados e os valores chave de um índice são alterados ou se a linha
é movida para uma página diferente, o controlo de transações do
SQL Server garante que todos os índices afectados são modificados
para reflectir essas alterações. Com o controlo de transações, as
operações em índices são executadas como sendo operações
atómicas. As acções são registadas e completamente recuperadas na
eventualidade de uma falha de sistema.
Figura 4: Um Clustered Index com os dados no nível folha.
Página 34
Instituto Superior de Engenharia do Porto
2.1.7)
O Page Manager e o Text Manager
O page manager e o text manager colaboram para gerir a
colecção de páginas como bases de dados identificadas (named
databases). Cada base de dados é constituída por um conjunto de
páginas em disco com 8 Kb, que estão espalhadas por um ou mais
ficheiros físicos.
O SQL Server utiliza oito tipos de páginas em disco: data pages,
text/image pages, index pages, Page Free Space (PFS) pages, Global
Allocation Map (GAM e SGAM) pages, Index Allocation Map (IAM)
pages, Bulk Changed Map pages e Differential Changed Map pages.
Todos os dados, excepto os tipos de dados text, ntext e image, são
armazenados em data pages. Estes três tipos de dados, que são
utilizados para armazenar grandes quantidades de informação (até 2
Gb cada de texto ou dados binários), podem utilizar o seu próprio
conjunto separado de páginas. Assim os dados não são tipicamente
armazenados em páginas de dados normais com o resto dos
registos. Em vez disso, um apontador na página de dados identifica a
página de início e o offset dos dados text/image. No entanto, no SQL
Server 2000, grandes objectos de dados que contenham apenas
alguns bytes podem opcionalmente ser armazenados na própria linha
de dados. As index pages armazenam as B-Trees que permitem o
acesso rápido aos dados. Páginas PFS mantém um controlo sobre
quais as páginas de uma base de dados que podem conter novos
dados. As allocation pages (GAM, SGAM e IAM) mantém controlo
sobre as outras páginas. Elas não contém qualquer registo da base
de dados e são utilizadas apenas internamente. As páginas Bulk
Changed Map e Differential Changed Map são utilizadas para backup
e recuperação de uma forma mais eficiente.
O page manager aloca e desaloca todos os tipos de páginas em
disco, organizando extents de oito páginas cada. Um extent pode ser
uniforme, onde todas as oito páginas alocadas são do mesmo objecto
(tabela ou índice), ou misto, que pode conter páginas de múltiplos
objectos. Se um objecto utiliza menos de oito páginas, o page
manager aloca novas páginas para esse objecto a partir de extents
mistos. Quando o tamanho de um objecto excede oito páginas, o
page manager aloca novo espaço para esse objecto em unidades de
extents uniformes inteiros. Esta optimização evita o overhead da
alocação de acontecer sempre que uma nova página é necessária
para grandes tabelas; este overhead apenas acontece a cada oito
vezes. Talvez mais importante, esta optimização força os dados da
mesma tabela a serem contínuos, na sua maioria. Ao mesmo tempo,
a capacidade para utilizar extents mistos impede o SQL Server de
Página 35
Instituto Superior de Engenharia do Porto
desperdiçar espaço se uma base de dados contiver várias tabelas
pequenas.
Para determinar a continuidade dos dados de uma tabela,
podemos utilizar o comando DBCC SHOWCONTIG. Uma tabela com
muita alocação e desalocação pode ficar muito fragmentada. A
reconstrução do clustered index (o que também reconstrói a tabela)
ou executar DBCC INDEXDEFRAG podem melhorar o desempenho,
especialmente se a tabela for acedida com frequência utilizando
index s Programa baseado numa rotina pequena que substitui um
programa mais longo, possivelmente para ser carregado mais
rápidamente ou remotamente. Por exemplo, um programa que utilize
RPC é compilado com stubs que substituem o programa que requer
um procedimento remoto. O stub aceita o pedido e depois reenvia-o
(através de outto programa) para o procedimento remoto. Quando
esse procedimento acabar o seu serviço, retorna o resultado ou outro
estado ao stub que o passa ao programa que fez o pedido.cans
ordenados.
2.1.8)
O Transaction Manager
Uma característica base do SQL Server é a sua capacidade para
garantir que as transacções seguem as ACID properties. As ACID
properties
significam:
atomicidade
(atomicity),
consistência
(consistency), isolamento (isolation) e durabilidade (durability). As
transacções devem ser atómicas, ou seja, tudo ou nada. Se uma
transacção fez COMMIT17, deve ser recuperável pelo SQL Server
independentemente da situação - mesmo se ocorrer uma falha total
do sistema um milisegundo após a confirmação do COMMIT. No SQL
Server se um trabalho estava a ser executado e houve uma falha de
sistema antes de a transacção ter feito COMMIT, todo o trabalho
sofre um ROLL BACK18 para o estado em que se encontrava antes de
o trabalho ter sido iniciado. O write-ahead logging torna sempre
possível efectuar um ROLL BACK de trabalho em progresso ou um
ROLL FOWARD de trabalho que já fez COMMIT mas que ainda não foi
aplicado às páginas de dados. O write-ahead logging garante que as
17
Acção que confirma a execução completa e com sucesso de uma
transacção. Quando uma transação efectua COMMIT, significa que todas as
escritas/leituras físicas ocorreram com sucesso e foram devidamente registadas no
registo de transacções
18
Ao contrário do COMMIT, um ROLL BACK identifica uma situação em que
uma ou todas as acções de uma transação falharam e tem que ser desfeitas. A
anulação dessas acções é feita mediante informação do registo de transacções e
garante a integridade dos dados.
Página 36
Instituto Superior de Engenharia do Porto
alterações de uma transacção – as before e after images – são
armazenadas em disco no registo de transacções antes de uma
transacção fazer COMMIT. As escritas para o registo de transacções
são sempre síncronas – isto é, o SQL Server tem que aguardar que
elas terminem. Escritas para páginas de dados podem ser
assíncronas porque todos os efeitos podem ser reconstruídos a partir
do registo se tal for necessário. O transaction manager coordena a
escrita no registo de transacções, recuperação e gestão do buffer.
O transaction manager define os limites das instruções que devem
ser agrupadas para formar uma operação. Controla transacções que
atravessam bases de dados no mesmo servidor SQL Server e permite
sequências de transacções encadeadas. Para uma transacção
distribuída para outro SQL Server (ou outro gestor de recursos), o
transaction manager coordena-se com o serviço Microsoft Distributed
Transaction Coordinator (MS DTC) utilizando remote procedure calls
(RPC). O transaction manager marca ponto de salvaguarda, que
permite designar locais dentro de uma transacção onde um trabalho
pode ser parcialmente desfeito ou ROLLED BACK.
O transaction manager também se coordena com o lock manager
no que se relaciona com libertação de bloqueios, baseado no nível de
isolamento. O nível de isolamento em que uma transacção é
executada determina qual a sensibilidade da aplicação a alterações
efectuadas por outras e consequentemente o tempo que essa
aplicação deve manter bloqueios para se proteger contra essas
alterações. Existem quatro níveis de isolamento disponíveis no SQL
Server 2000: Uncommited Read (também designado dirty read),
Commited Read, Repeatable Read e Serializable.
O comportamento de uma transacção depende do nível de
isolamento. Vamos analisar esses níveis, embora uma completa
compreensão dos níveis de isolamento implique uma compreensão
do bloqueio (locking) uma vez que estão intimamente ligados.
2.1.8.1) Uncommited Read
Uncommited Read, ou dirty read, permite que uma transacção leia
qualquer conjunto de dados contido numa página de dados, tenham
ou não esses dados efectuado COMMIT. Por exemplo, outro utilizador
pode estar a executar uma transacção que actualize dados e, apesar
de ter exclusive locks sobre os dados, outra transação poderia lê-los
na mesma. O outro utilizador poderia posteriormente decidir efectuar
um ROLL BACK da sua transacção, o que, para todos os efeitos, seria
como se essa transacção nunca tivesse ocorrido. Se fosse um
sistema mono-utilizador e todos os pedidos permanecessem numa
fila de espera para aceder aos dados, as alterações não seriam
Página 37
Instituto Superior de Engenharia do Porto
visíveis. Mas num sistema multi-utilizador, os dados seriam lidos e
seriam efectuadas acções sobre eles. Embora este cenário não seja
desejável, com uncommited read não ficaríamos à espera que um
lock fosse libertado, nem as nossas leituras emitiriam shared locks
que afectassem outros.
Quando se utiliza uncommited reads perde-se a garantia de dados
altamente consistentes em favor de alta concorrência no sistema
sem que os utilizadores se bloqueiem uns aos outros. Afinal quando
se deve utilizar uncommited reads? Claramente que não devem ser
utilizados em aplicações financeiras onde cada valor deve ser
coerente e correcto. No entanto, seria possível para certas aplicações
de suporte à decisão – por exemplo, análise de tendências de vendas
– onde precisão não é necessária e a troca por alto nível de
concorrência justifica a sua utilização.
2.1.8.2) Commited Read
Commited Read é o nível de isolamento por defeito do SQL
Server. Garante que uma operação nunca lê dados que outra alterou
e ainda não efectuou COMMIT. (Ou seja, nunca lê dados que
logicamente nunca existiram). Com commited read, se uma
transacção está a alterar dados e consequentemente detêm um
exclusive lock em linhas de dados, outras transações devem,
aguardar que esses locks sejam libertados antes de utilizarem os
dados (sejam leituras ou alterações). Também, uma transacção deve
colocar share locks (no mínimo) sobre os dados que vão ser
visitados, o que significa que os dados podem estar indisponíveis
para que outros os utilizem. Um share lock não impede que outros
leiam os dados, mas faz com que aguardem para efectuar alterações.
Os shared locks podem ser libertados após os dados terem sido
enviados para o cliente que efectuou o pedido – não têm que ser
mantidos durante toda a duração da transacção.
2.1.8.3) Repeatable Read
O nível de isolamento repeatable read adiciona às propriedades do
committed read a garantia que se uma transacção torna a visitar
dados ou se uma query é reemitida, os dados não sofreram
alterações. Por outras palavras, executando a mesma pesquisa duas
vezes dentro de uma transacção não vai receber alterações aos
valores dos dados efectuados por uma transacção de outro utilizador.
No entanto, o nível de isolamento repeatable read não permite que
registos “fantasma” apareçam.
Página 38
Instituto Superior de Engenharia do Porto
Prevenir que apareçam nonrepeatable reads é uma garantia
desejável. O custo de esta garantia extra é de que todos os shared
locks numa transacção têm que ser mantidos até ao fim (COMMIT ou
ROLLBACK) de uma transacção. Nenhum outro utilizador pode
modificar dados visitados por esta transacção enquanto esta
transacção estiver em processamento. Obviamente, isto pode reduzir
imenso a concorrência e degradar o desempenho. Se as transacção
não forem pequenas ou se as aplicações não forem escritas para ter
em conta potenciais questões de contenção destes locks, o SQL
Server
vai
aparentar
uma
“paragem”
enquanto
aguarda
simplesmente pela libertação dos bloqueios.
2.1.8.4) Serializable
O nível de isolamento serializable adiciona ao repeatable read a
garantia de que se uma query é relançada, não vão ser adicionados
registos. Por outras palavras, não vão aparecer “fantasmas” se a
mesma consulta é feita duas vezes no interior de uma transacção.
Mais precisamente, os níveis serializable e repeatable read afectam a
sensibilidade às alterações efectuadas por outras conexões, sendo ou
não o ID do utilizador o mesmo. Cada transação em SQL Server tem
o seu próprio espaço de transacção e bloqueio.
Prevenir o aparecimento de “fantasmas” é outra garantia
desejável. Mas, mais uma vez, enfrentamos problemas de custos
adicionais. Os custos adicionais deste nível são semelhantes aos do
repeatable read – todos os shared locks numa transacção devem ser
mantidos até ao final da transacção. Adicionalmente, implementar o
nível de isolamento serializable requer que não só os dados que são
lidos mantenham o bloqueio, mas também que existam lock nos
dados que “não existem”! Por exemplo, suponhamos que no interior
de uma transacção é executada uma instrução SELECT para ler os
dados de todos os clientes que têm um código postal entre 1000 e
4000, e na primeira execução nenhum registo verifica esta condição.
Para implementar o nível de isolamento serializable, deve-se
bloquear o conjunto de potenciais registos com o código postal entre
1000 e 4000 de forma a que se a mesma consulta é executada, não
existam linhas que verifiquem a condição. O SQL Server garante isto
através da utilização de um tipo de bloqueio especial denominado
key-range lock. O nome serializable advém do facto que executar
várias transacções em simultâneo é igual a executá-las em
sequência, ou seja, em série. Por exemplo, suponhamos as
transacções A, B e C a ser executadas simultaneamente e cada uma
a tentar actualizar os mesmos dados. Se a sequência em que as
transacções conseguem locks do conjunto de dados é B, C e A, os
resultados obtidos por executar todas simultaneamente é o mesmo
Página 39
Instituto Superior de Engenharia do Porto
do que executar as transacções na sequência B, C e A. O nível
serializable não implica que se conheça previamente a ordem. A
ordem é considerada um evento aleatório. Mesmo num sistema
mono-utilizador, a ordem das transacções a chegarem è fila de
espera seria essencialmente aleatória. Se a ordem do batch for
importante numa aplicação, deve ser implementado um sistema puro
de batch.
A parte complicada da gestão de transacções,
operações de rollback/rollforward e recuperação.
2.1.9)
é
garantir
O Lock Manager
O bloqueio é uma função crucial de um sistema de gestão de
bases de dados multi-utilizador tal como o SQL Server. O SQL Server
permite a gestão de múltiplos utilizadores simultaneamente e
garante que as transacções observam as propriedades do nível de
isolamento escolhido. No nível superior, serializable, o SQL Server
deve levar o sistema multi-utilizador a actuar como um sistema
mono-utilizador – apesar de cada utilizador estar em fila de espera
para utilizar o sistema sem actividade de outros. O lock guarda os
dados e os recursos internos que tornam possível a vários
utilizadores em simultâneo utilizar a base de dados e não afectar
seriamente a utilização de outro utilizador.
O lock manager adquire e liberta vários tipos de locks, tais como
shared locks para leitura, exclusive locks para alocação de espaço,
etc. Gere a compatibilidade entre tipos de locks, resolve deadlocks,
escala locks se necessário. O lock manager controla locks de tabelas,
páginas e linhas além de locks de dados de sistema. (Os dados de
sistema, tais como cabeçalhos e índices de páginas, são privados do
sistema de base de dados).
O lock manager fornece dois tipos de sistemas de lock. O primeiro
permite row locks, page locks e table locks para todos as data tables,
data pages e rows, text pages e leaf-level index pages e index rows.
O segundo sistema de locking é utilizado internamente apenas para
dados restritos de sistema; protege a raiz e páginas intermédias dos
índices enquanto estes estão a ser atravessados. Este mecanismo
interno utiliza latches, uma variação mais leve e de curta duração de
locks de dados que não necessita de bloqueio até ao fim da
transacção. Se fossem utilizados locks completos isso atrasaria o
sistema. Adicionalmente à protecção dos níveis superiores dos
índices, os latches protegem as linhas enquanto elas estão a ser
transferidas do motor de armazenamento para o motor relacional. Se
se examinar os locks através do stored procedure sp_lock ou de um
mecanismo semelhante que receba a sua informação da tabela de
Página 40
Instituto Superior de Engenharia do Porto
sistema syslocksinfo, não se vem os latches; apenas se visualizam os
locks de dados. No entanto, estão disponíveis contadores no System
Monitor para monitorizar pedidos de latches, aquisições e libertações.
2.1.10)
Outros Gestores
Também incluído no motor de armazenamento existem gestores
para controlar utilitários tais como bulk loads, comandos DBCC,
operações de backup e restore e o Virtual Device Interface (VDI). O
VDI permite que programadores construam os seus próprios
utilitários de backup e restore e acedem directamente às estruturas
de dados do SQL Server, sem necessitar de aceder através do motor
relacional. Existe um gestor para controlar operações de ordenação e
outro para manter fisicamente os ficheiros e dispositivos de backup
em disco.
2.2)
A GESTÃO DE MEMÓRIA
Um dos principais objectivos do SQL Server 2000 é a facilidade de
escalar o sistema onde é instalado. Desde um computador portátil
com Windows 98 até a um servidor poderoso a correr Windows 2000
DataCenter Server. Para que esta política funcione é necessário que
a gestão de memória seja implementada de uma forma robusta. Por
defeito, o SQL Server 2000 ajusta a sua utilização da memória do
sistema de forma a balancear as necessidades das outras aplicações
a correrem na mesma máquina e as necessidades dos seus
componentes internos.
Quando se determina a quantidade óptima de memória para ser
atribuída dinamicamente ao SQL Server, o memory manager tenta
deixar pelo menos 4 Mb livres para o sistema operativo. O tamanho
reservado para o sistema é parcialmente determinado pelo tempo
estimado de vida de uma página de cache em memória. O memory
manager determina um valor para Life Expectancy que indica
quantos segundos, em média, uma página fica em cache se não for
utilizada. O Performance Monitor tem um contador que permite
visualizar o valor corrente de Life Expectancy. Este valor é apenas
uma estimativa e é baseado na velocidade a que o Lazywriter verifica
referências a páginas e o valor total de memória disponível. Se o
valor de Life Expectancy de uma página é pequeno, o memory
manager tenta manter a memória reservada a cerca de 4 Mb para
aumentar a memória disponível para o SQL Server. Se o valor de Life
Expectancy aumenta, o tamanho de memória reservada para o
sistema operativo aumenta para cerca de 20 Mb e a memória total
Página 41
Instituto Superior de Engenharia do Porto
para o SQL Server diminui. Todas as instância do SQL Server na
mesma máquina trabalham para o mesmo valor reservado e Life
Expectancy.
Como uma alternativa à computação dinâmica de memória, o SQL
Server pode ser configurado para um valor fixo de memória. Quer a
atribuição de memória seja dinâmica ou um valor fixo, o espaço de
memória total para cada instância é considerado como uma cache
unificada e é gerida como uma colecção de pools com as suas
próprias políticas e finalidades. A memória pode ser requisitada e
atribuída a qualquer um dos vários componentes internos.
2.2.1)
O Buffer Manager e Memory Pools
O principal componente de memória no SQL Server é o buffer
pool. Toda a memória não utilizada por outro componente de
memória fica em buffer pool. O buffer manager faz a gestão de
funções de I/O de disco para leitura de dados e páginas de índices
para o buffer pool de forma a que os dados possam ser partilhados
pelos utilizadores. Quando outros componentes requisitam memória,
podem requisitar um buffer do buffer pool. Um buffer é uma página
em memória que tem o mesmo tamanho que uma página de dados
ou página de índice.
Outro pool de memória é o próprio sistema operativo.
Ocasionalmente, o SQL Server tem que requisitar blocos contínuos
de memória maiores que os 8 Kb de página que o buffer pool pode
fornecer. Tipicamente, a utilização de grandes blocos de memória
está limitada ao mínimo, de forma a que a utilização de memória do
SQL Server faça poucas chamadas directas ao sistema operativo.
Podemos associar a procedure cache como outro memory pool,
onde as árvores de pesquisa e os planos de execução de stored
procedures, triggers, funções de utilizador e ad hoc queries são
armazenados. Outras pools são utilizadas por queries com alta
utilização de memória que utilizam hashing (a definição de hashing
no SQL Server irá ser descrita posteriormente) ou ordenação e por
objectos especiais de memória que necessitam de menos de 8 Kb de
página.
Página 42
Instituto Superior de Engenharia do Porto
2.2.2)
Acesso a In-Memory Pages
O acesso a páginas no buffer pool deve ser rápido. Mesmo com
memória real, seria ineficiente termos que percorrer toda a cache por
uma página quando temos centenas de Mb de dados. Para evitar esta
ineficiência, as páginas em buffer pool passam por funções de hash
para serem de acesso rápido. O Hashing é uma técnica que mapeia
uniformemente uma chave através de uma função de hash a um
conjunto de hash buckets. Um hash bucket é uma estrutura em
memória que contém um vector de ponteiros (implementado como
uma lista ligada) para as páginas do buffer. Se todos os ponteiros
para páginas do buffer não cabem numa página de hash, uma lista
ligada liga a páginas de hash adicionais.
Através de um identificador dbid-fileno-pageno (o primeiro valor
identifica a base de dados, o segundo o ficheiro físico e o último a
página de dados), a função de hash converte a chave para o hash
bucket que deve ser verificado; essencialmente, o hash bucket
funciona como um índice para a página especifica necessária. Através
da utilização de hashing, mesmo quando grandes conjuntos de
memória são utilizados, o SQL Server pode encontrar uma página de
dados específica em cache com apenas algumas leituras de memória.
De forma semelhante, são necessárias apenas algumas leituras de
memória para determinar que a página necessária não está em
cache e é necessário lê-la do disco.
2.2.3)
Acesso a Free Pages (Lazywriter)
Uma página de dados ou de índice só pode ser utilizada se estiver
em memória. Assim, um buffer no buffer pool deve estar disponível
para que a página possa ser lida para ele. Manter um conjunto de
buffers disponíveis para uso imediato é uma optimização de
desempenho importante. Se um buffer não está rapidamente
disponível, muitas páginas de memória podem ter que ser
pesquisadas para localizar um buffer que possa ser libertado.
O buffer pool é gerido por um processo chamado lazywriter que
utiliza um algoritmo cíclico para atravessar o buffer pool.
Basicamente, o lazywriter visita cada buffer e determina se esse
buffer foi referenciado desde a última passagem através de um
contador no cabeçalho do buffer. Se o valor de referência não é 0, o
buffer continua em pool e o seu valor de referência é decrementado
em preparação para a próxima passagem; caso contrário, o buffer é
disponibilizado para ser reutilizado.
Página 43
Instituto Superior de Engenharia do Porto
O valor de referência dum buffer é incrementado de cada vez que
o seu conteúdo é acedido por um processo. Para páginas de dados ou
índices, este valor é incrementado em uma unidade. Mas objectos
com custos maiores de criação, tais como planos de execução de
stored procedures, têm um valor de referência mais elevado que
reflecte o seu “valor de substituição”. Quando o lazywriter passa e
verifica as páginas que foram referenciadas, não utiliza simplesmente
uma decrementação. Divide o valor de referência por 4. Isto significa
que páginas referenciadas com frequência e as valor de substituição
elevado são favorecidas, pelo que o seu contador não chegará a 0
tão rapidamente, mantendo-as em pool. O lazywriter passa através
do buffer pool quando o número de páginas disponíveis na lista de
disponibilidades cai abaixo do seu valor mínimo. O valor mínimo é
calculado como sendo uma percentagem do tamanho total do buffer
pool que está sempre entre 128 Kb e 4 Mb. O SQL Server calcula as
necessidades de páginas livres baseado na carga do sistema e no
número de paragens ocorridas. Uma paragem ocorre quando um
processo necessita de uma página livre e nenhuma está disponível; o
processo “adormece” e aguarda que o lazywriter liberte algumas
páginas. Se ocorrem muitas paragens o SQL Server aumenta o
tamanho mínimo de disponibilidades. Se a carga sobre o sistema é
leve e poucos stalls ocorrem, esse valor é reduzido e as páginas em
excesso podem ser utilizadas para hash de páginas de dados e de
índices ou planos de execução adicionais. Estes valores podem ser
verificados através de contadores no Performance Monitor.
Threads do utilizador também executam a mesma função de
pesquisa de páginas que podem ser libertadas. Isto acontece quando
um processo do utilizador necessita de ler uma página do disco para
um buffer. Quando uma leitura é inicializada, a thread do utilizador
verifica se as disponibilidades são reduzidas. Em caso afirmativo, a
thread do utilizador age como o lazywriter e verifica se existem
buffers que possam ser libertados. A razão para ter threads de
utilizador a partilhar o trabalho do lazywriter é para distribuir os
custos por todos os processadores num ambiente SMP. De facto, o
SQL Server 2000 tem uma lista de disponibilidades separada para
cada processador para ajudar ainda mais à distribuição de custos e
para melhorar a escalabilidade. Uma thread do utilizador que
necessite de uma página livre verifica primeiro a lista de
disponibilidades para o processador onde é executada, verificando as
listas do outros processadores apenas se não existir nenhuma página
livre.
Página 44
Instituto Superior de Engenharia do Porto
2.2.3.1) Manter páginas em cache permanentemente
Podemos marcar tabela de forma a que as suas páginas nunca
sejam libertadas e desta forma mantidas em memória
indefinidamente. Este processo é designado por pinning de uma
tabela. Qualquer página (dados, índices ou text19) pertencentes a
uma tabela marcada nunca é marcada como disponível e nunca é
reutilizada a não ser que seja desmarcada. O Pinning ou unpinnig é
efectuado utilizando a opção pinnable do stored procedure
sp_tableoption. Atribuir o valor TRUE a esta opção para uma tabela
não faz com que a tabela seja lida para cache, nem marca as páginas
desta como favorecidas de alguma forma; em vez disso, é evitado o
overhead desnecessário e simplesmente não se permite que as
páginas pertencentes a essa tabela possam ser colocadas na lista de
disponibilidades para possível substituição.
Uma vez que mecanismos como o write-ahead logging e o
checkpointing não são afectados, tal operação não implica de forma
alguma recuperação. No entanto, o pinning de muitas tabelas pode
resultar em poucas ou nenhuma páginas disponíveis em memória
quando um novo buffer é necessário.
Páginas que são acedidas com frequência nunca são colocadas na
lista de disponibilidades. Uma página que tem um valor do contador
diferente de 0, tal como uma página lida ou criada recentemente,
não é adicionada à lista de disponíveis até que o seu contador caia a
0. Antes deste ponto, é claramente acedida com frequência e não é
uma boa candidata a ser reutilizada. Páginas com acesso
extremamente frequente podem nunca ser libertadas, mesmos que
os seus objectos não tenham sido marcados (pinned).
2.2.4)
Checkpoints
As operações de checkpoint minimizam o trabalho que o SQL
Server deve executar quando as bases de dados são recuperadas no
arranque do sistema. Os checkpoints são executados base de dados
a base de dados. Eles descarregam dirty pages para disco de forma a
que essas alterações não tenham que ser refeitas durante a
recuperação da base de dados. Uma dirty page é uma página que foi
modificada desde que foi carregada de disco para o buffer pool.
19
Os tipo de dados text, ntext e image são armazenados em páginas
separadas devido à sua dimensão (tamanho máximo de 2 Gb de dados).
Página 45
Instituto Superior de Engenharia do Porto
Quando ocorre um checkpoint, o SQL Server escreve um registo de
checkpoint no registo de transacções, que lista todas as transacções
que estão activas. Isto permite que o processo de recuperação
construa uma tabela contendo uma lista de todas as potenciais dirty
pages.
Os checkpoints são activados quando:
•
Um dono de uma base de dados emite um comando
checkpoint para efectuar um checkpoint sobre essa base de
dados.
•
O log está a ficar cheio (mais de 70% da sua capacidade) e
a base de dados está em modo de recuperação SIMPLE ou a
opção trunc log on chkpt está activa. Um checkpoint é
disparado para truncar o transaction log e libertar espaço.
No entanto, se nenhum espaço pode ser liberto, talvez
devido a uma longa transacção, não ocorre um checkpoint.
•
É estimado um tempo de recuperação longo. Quando o
tempo de recuperação é previsto como sendo superior ao
valor da opção de configuração recovery interval, um
checkpoint é disparado. O SQL Server 2000 utiliza uma
métrica simples para prever o tempo de recuperação porque
pode recuperar, ou refazer, em menos tempo do que foi
necessário na operação original. Assim, se os checkpoint são
disparados pelos menos com a frequência do recovery
interval, a recuperação é completada dentro do intervalo.
Um intervalo de recuperação com o valor 1 significa que os
checkpoints ocorrem a cada minuto durante a execução de
uma transacção na base de dados. Uma quantidade mínima
de trabalho deve ser efectuada para que o disparo
automático do checkpoint seja atingido; cerca de 10 Mb de
log por minuto. Desta forma o SQL Server não desperdiça
tempo com bases de dados sem transacções. Um valor de 0
significa que o SQL Server escolhe o valor apropriado
automaticamente; na versão corrente, é de 1 minuto.
Num sistema com uma grande quantidade de memória, os
checkpoints podem gerar potencialmente muitas operações de
escrita para forçar todas as dirty pages para disco. Para limitar a
quantidade de recursos que os checkpoints consomem, o SQL Server
limita o número de checkpoints de uma transacção a um máximo de
100 operações de escrita concorrentes. Pode parecer um valor
grande, mas num sistema de grande dimensão, mesmo 100
operações concorrentes podem demorar muito tempo a escrever
todas as dirty pages. Para optimizar os checkpoints e para garantir
que estes não necessitam de efectuar mais trabalho do que o
necessário, o algoritmo de checkpoint controla um valor gerado para
Página 46
Instituto Superior de Engenharia do Porto
cada buffer na cache. Sem este valor de controlo, os checkpoints
poderiam escrever as mesmas páginas para disco várias vezes.
O processo de checkpoint atravessa o buffer pool, avaliando as
páginas por ordem de número de buffer e, quando encontra uma
dirty page, pesquisa por páginas físicas contíguas (em disco) que
também estão “dirty” para poder efectuar uma escrita de um grande
bloco. Isto significa que poderia, por exemplo, escrever as páginas
14, 200, 260 e 1000 quando descobre que a página 14 está “dirty”
(estas páginas podem ter localizações físicas contíguas mesmo que
estejam separadas no buffer pool). Quando o processo continua a
verificar o buffer pool, chega à página 1000. Potencialmente, esta
página pode estar outra vez “dirty”, e pode ser escrita uma segunda
vez. Quanto maior o buffer pool, maiores as hipóteses de um buffer
que já foi escrito se tornar “dirty” antes do checkpoint finalizar. Para
evitar esta situação, cada buffer tem um bit associado designado
generation number. No início do checkpoint, todos os bits são
modificados para o mesmo valor, ou todos a 0 ou todos a 1. Quando
um checkpoint verifica uma página, modifica o valor para o oposto.
Quando o checkpoint encontra uma página onde o valor já foi
alterado, não escreve essa página. Também, todas as novas páginas
carregadas para o buffer durante o checkpoint, recebem o novo valor
de generation number; assim não vão ser escritas durante este ciclo
de checkpoint. Qualquer página já escrita por se encontrar na
vizinhança de outra não vai ser escrita.
2.2.5)
Acesso
Manager
a
Páginas
utilizando
o
Buffer
O Buffer Manager gere a versão em memória de cada página física
de disco e fornece a todos os outros módulos acesso a estas (com as
medidas de segurança apropriadas). A imagem da memória no buffer
pool, se existir, tem precedência sobre a imagem do disco. Se a
página está “dirty”, a cópia em memória da página de dados inclui
actualizações que não foram ainda escritas em disco. Quando uma
página é necessária para um processo, tem que existir em memória
no buffer pool. Se a página não existe, um I/O físico é executado
para a obter. Obviamente, devido aos custo de um I/O físico, quanto
menos I/O físicos forem executados melhor. Quanto mais memória
existir (maior o buffer pool), mais páginas podem existir em memória
e maior as probabilidades de ela poder ser encontrada lá.
Uma base de dados é vista como uma sequência de páginas
numeradas. O identificador dbid-fileno-pageno especifica unicamente
uma página para o ambiente do SQL Server. Quando outro módulo
(tais como o access method manager, row manager, index manager
Página 47
Instituto Superior de Engenharia do Porto
ou text manager) necessita acesso a uma página, requer o acesso
através do buffer manager através do identificador dbid-filenopageno.
O buffer manager responde à chamada do módulo com um
ponteiro para o buffer de memória que contém essa página. A
resposta pode ser imediata se a página já se encontra em cache ou
pode demorar um instante para um I/O de disco completar e
carregar a página em memória. Tipicamente, o módulo que efectua a
chamada também requisita que o lock manager efectue o lock
apropriado para essa página. O módulo informa o buffer manager se
e quando acabar de alterar a página. O buffer manager é responsável
por escrever essas alterações para disco de forma coordenada com a
gestão de logging e transacção.
2.2.6)
Questões
Relacionadas
Quantidades de Memória
com
Grandes
Sistemas com várias centenas de Mb de RAM não são incomuns.
De facto, para questões de benchmarking a Microsoft utiliza sistemas
com até 2 Gb de memória RAM física. A versão Enterprise Edition do
SQL Server permite a utilização de ainda maiores quantidades de
memória. A razão para termos uma máquina com grande quantidade
de memória é para minimizar os I/O físicos de disco aumentado o
cache-hit ratio.
A Enterprise Edition do SQL Server 2000 num sistema com
Windows 2000 permite a quantidade de memória que o Windows
2000 Advanced Server ou Windows 2000 DataCenter Server aceitam
utilizando a API Address Windowing Extensions (AWE) para suportar
grandes quantidades de memória. Deve-se especificar na
configuração de uma instância do SQL Server a utilização das
extensões AWE; a instância pode então suportar até 8 Gb de
memória física num Windows 2000 Advanced Server e 64 Gb de
memória física num Windows 2000 DataCenter Server. Apesar do
endereçamento de 32-bits standard só suportar 4 Gb de memória
física, as extensões permitem que a memória adicional seja utilizada
como memória não paginada. O memory manager podem então
mapear dinamicamente vistas da memória não paginada para o
espaço de endereçamento de 32-bits.
Página 48
Instituto Superior de Engenharia do Porto
2.2.6.1) Read Ahead
O SQL Server suporta um mecanismo denominado read ahead,
onde a necessidade de dados e índices pode ser antecipada e as
páginas carregadas no buffer pool antes de serem efectivamente
lidas. Esta optimização de desempenho permite que grandes
quantidades de dados sejam processados. Este mecanismo é gerido
internamente e não são necessários ajustes de configuração.
Adicionalmente, o read ahead não utiliza threads de sistema
separados. Isto garante que o read ahead está em avanço, mas não
demais, sobre a leitura efectiva dos dados.
Existem dois tipos de read ahead: um para table scans em heaps
e outro para index ranges. Para table scans, a estrutura de alocação
da tabela é consultada para ler a tabela em ordem de
armazenamento em disco. Até 32 extents (32 * 8 paginas/extent *
8192 bytes/página = 2 Mb) de read ahead estão a aguardar de cada
vez. Quatro extents (32 páginas) de cada vez são lidas com uma
simples scatter read de 256 Kb. Se a tabela estiver dispersa por
múltiplos ficheiro num grupo de ficheiro (file group), o SQL Server
tem uma read ahead thread por ficheiro. Na versão Standard Edition
do SQL Server 2000, cada thread pode ler até 4 extents de cada vez
para um ficheiro e até 32 ficheiros podem ser processados
concorrentemente. Isto significa que as threads de read ahead
podem processar até 128 páginas de dados. No SQL Server
Enterprise Edition, podem ser lidos mais extents de cada ficheiro e
mais ficheiros podem ser processados concorrentemente. Aliás, não
existe definido um limite e extents ou ficheiros para esta versão,
podendo ler em avanço até 1% do buffer pool.
Para index ranges, é utilizado o primeiro nível da estrutura do
índice (nível anterior ao nível folha) para determinar as páginas a ler
em avanço. Quando é iniciada a consulta ao índice, o read ahead é
invocado na descida inicial do índice para minimizar o número de
leituras efectuadas. Por exemplo, para uma consulta de WHERE
state=’WA’, o read ahead pesquisa o índice pela chave=’WA’ e pode
dizer pelos nós de primeiro nível quantas páginas tem que ser
examinadas para satisfazer a consulta. Se o número de páginas
antecipadas é pequeno, todas as páginas são requisitadas pelo read
ahead inicial; se as páginas são contíguas, são lidas em scatter
reads. Se contém um grande número de páginas, o read ahead inicial
é executado e a partir daí a cada 16 páginas utilizadas pela consulta,
o índice é consultado para serem lidas mais 16 páginas. Isto tem
vários efeitos interessantes:
Página 49
Instituto Superior de Engenharia do Porto
•
Gamas pequenas podem ser processadas numa simples
leitura no nível das páginas de dados sempre que o índice é
contíguo.
•
O scan range (por exemplo, state=’WA’) pode ser utilizado
para prevenir leituras em avanço de páginas que não vão
ser utilizadas uma vez que esta informação está disponível
no índice.
•
O read ahead não é atrasado por ter que seguir ligações de
páginas ao nível das páginas de dados. (O read ahead pode
ser efectuado quer em clustered indexes quer em
nonclustered indexes).
2.2.6.2) Merry-Go-Round Scans
A Enterprise Edition do SQL Server 2000 incluí outra optimização
para melhorar a performance de nonordered scans (uma consulta
que não é pedida numa ordem específica), particularmente em
múltiplas consultas desordenadas da mesma tabela requisitadas
simultaneamente por vários processos. Sem esta optimização, um
processo podia iniciar uma consulta e chegar a 20% do caminho
através da tabela antes de outro processo requisitar os mesmos
dados. Se a cache é pequena ou está a ser utilizada por outros
processos para dados completamente não relacionados, as páginas
consultadas pelo processo original podem ter sido trocadas, o que
significa que o buffer manager tem que retornar ao disco para ler as
primeiras páginas outra vez. Quando a consulta original recomeçar,
qualquer página lida em avanço pode ter desaparecido e mais
leituras
de
disco
são
necessárias.
Isto
pode
provocar
desfragmentação de disco. Uma nova optimização denominada
Merry-Go-Round Scans permite ao SQL Server 2000 Enterprise
Edition evitar esta situação por permitir que o segundo processo se
inicie no mesmo ponto que o processo original chegou. Ambos os
processos podem assim ler os mesmos dados, e cada página pode
ser lida de disco apenas uma vez e ser utilizada por ambas as
consultas. Quando o primeiro processo terminar, o segundo pode ler
os 20% iniciais da tabela. A Figura 5 ilustra um Merry-Go-Round
Scan.
Página 50
Instituto Superior de Engenharia do Porto
Figura 5: O Merry-Go-Round do SQL Server 2000 Enterprise Edition
2.2.6.3) O Log Manager
Todas as alterações são escritas em avanço pelo buffer manager
no transaction log. Isto significa que o log regista uma transacção em
disco antes das páginas de dados modificadas serem escritas. A
escrita em avanço do log garante que todas as bases de dados
podem ser recuperadas a um estado consistente, mesmo em caso de
uma falha completa de sistema, desde que o disco sobreviva. Um
processo nunca recebe confirmação que uma transacção efectuou
COMMIT a menos que esteja em disco no transaction log. Por esta
razão, todas as escritas no transaction log são síncronas - o SQL
Server deve esperar por uma confirmação de conclusão. As escritas
em páginas de dados podem ser assíncronas, sem terem que esperar
por confirmação, uma vez que se uma falha ocorrer a transação pode
ser desfeita ou refeita através da informação do transaction log.
O log manager formata os registos do transaction log em memória
antes de os escrever em disco. Para formatar estes registo de log, o
log manager mantém regiões contíguas de memória denominadas
Página 51
Instituto Superior de Engenharia do Porto
log caches. No SQL Server 2000, o registo de log não partilham o
buffer pool com as páginas de dados e índices. Os registos de log são
mantidos apenas nos log caches.
Para atingir maior capacidade, o log manager tem duas ou mais
log caches. Uma é a log cache corrente, onde os novos registos vão
ser adicionados. Adicionalmente, existem uma ou mais log caches
disponíveis para serem utilizadas quando o log cache corrente estiver
cheio. O log manager também mantém duas filas de espera de log
caches: uma flushQueue, que contém log caches cheias à espera de
serem descarregadas, e uma freeQueue, que contém log caches sem
dados (que foram descarregadas) e que podem ser reutilizadas.
Quando um processo de utilizador requisita o descarregar de uma
log cache específica (por exemplo, quando uma transacção efectua
COMMIT), a log cache é colocada em flushQueue. De seguida, a
thread (ou fiber) é colocada na lista de conexões e espera que a log
cache seja descarregada. A conexão não faz mais nada enquanto os
seus registos em log não forem descarregados.
O Log Writer é um processo dedicado que verifica a flushQueue
por ordem e descarrega as log caches para disco. As log caches são
escritas uma de cada vez. O log writer primeiro verifica se a log
cache é a log cache corrente. Se for, o log writer utiliza padding20
sobre a log cache e modifica alguma informação de cabeçalho.
Depois emite um evento I/O para esta log cache. Quando o
descarregar de uma log cache específica está terminada, qualquer
processo que aguarda por esta log cache é acordado e pode
continuar o trabalho.
2.3)
REGISTO DE TRANSACÇÕES E RECUPERAÇÃO
O registo de transacções regista todas as alterações efectuadas
sobre a base de dados e armazena informação suficiente para
permitir que qualquer alteração seja desfeita (rolled back) ou refeita
(rolled foward) na eventualidade de uma falha de sistema ou se for
ordenado para o fazer pela aplicação (no caso de uma instrução de
rollback). Fisicamente, o registo de transacções é um conjunto de
ficheiros associados a uma base de dados na altura de criação ou
alteração da base de dados. Módulos que efectuem alterações à base
de dados escrevem entradas no registo que descrevem exactamente
as alterações efectuadas. Cada entrada do registo é marcada com
um número de sequência de registo (log sequence number - LSN)
20
Informação adicional escrita sobre o log cache.
Página 52
Instituto Superior de Engenharia do Porto
que é garantidamente único. Todas as entradas do registo que fazem
parte da mesma transacção estão ligadas em conjunto de forma a
que todas as partes de uma transacção possam ser facilmente
encontradas para acções de anular ou refazer.
O buffer manager garante que o registo de transacção é escrito
antes das mudanças à base de dados serem escritas (write-ahead
logging). Isto é possível porque o SQL Server verifica a sua posição
actual no registo através do LSN. Cada vez que uma página é
mudada, o LSN correspondente a essa alteração é escrito no
cabeçalho da página de dados. As dirty pages podem ser escritas
para disco apenas quando o LSN da página é inferior ao LSN da
última página escrita no registo. O buffer manager também garante
que as páginas do registo são escritas numa ordem específica,
tornando claro quais as páginas a serem processadas na
eventualidade de uma falha de sistema, independentemente de
quando ocorreu a falha. As entradas do registo de uma transacção
são escritas para disco antes da confirmação de COMMIT ser enviada
ao processo do cliente, mas os dados alterados podem ainda não ter
sido fisicamente escritos nas páginas de dados. Assim sendo, apesar
das escritas no registo serem síncronas (o SQL Server tem que
aguardar que estas completem para ter a certeza que ficaram
guardadas em disco), as escritas em páginas de dados podem ser
assíncronas. Isto é, escritas em páginas de dados têm apenas que
ser anunciadas ao sistema operativo e o SQL Server pode verificar
depois se elas foram completadas. Não tem necessidade de acabar
logo uma vez que o SQL Server tem o registo que contém toda a
informação para refazer todo o trabalho, mesmo na eventualidade de
uma falha de corrente ou falha de sistema antes das escritas
completarem. O sistema seria muito mais lento se tivesse que
aguardar que cada acção de I/O acabasse antes de poder continuar.
Registar implica demarcar o início e fim de cada transacção (e
savepoints, se forem utilizados). Entre o início e fim, existe
informação sobre alterações efectuadas sobre os dados. Esta
informação pode tomar a forma de valores “antes e depois” ou pode
referenciar as operações que foram efectuadas de forma a que esses
valores possam ser derivados. O fim de uma transacção típica é
marcado com um registo COMMIT, que indica que uma transacção
tem que estar reflectida na base de dados ou refeita se necessário.
Uma transacção abortada durante execução normal devido a um
rollback explícito ou algo como uma falha de um recurso (não existir
memória disponível) na realidade desfaz a operação aplicando
modificações sobre os dados que tinham sido alterados pela
transacção abortada. As entradas destas alterações são escritas no
registo e marcadas como “compensation log records”. Se o sistema
falhar após uma transacção fazer COMMIT mas antes dos dados
serem escritos nas páginas de dados, a transacção tem que ser
Página 53
Instituto Superior de Engenharia do Porto
recuperada.
O
processo
de
recuperação
automaticamente no arranque do sistema.
é
executado
A recuperação executa tanto a operação de refazer (rollfoward) ou
desfazer (rollback). Numa operação de refazer, o registo é
examinado e cada modificação é verificada como sendo já reflectida
na base de dados (após esta acção, cada modificação efectuada pela
transacção está garantidamente aplicada). Se a modificação não
aparece na base de dados, é de novo executada a partir da
informação do registo. Desfazer implica a remoção de parte das
alterações efectuadas por uma transacção que não completou
inteiramente.
Durante a recuperação, apenas modificações que ocorreram ou
estão em aberto (em progresso) desde o último checkpoint são
refeitas ou desfeitas. Existem três fases que estão ilustradas na
Figura 6. A descrição refere-se a uma falha do SQL Server, mas estes
mesmo planos de recuperação ocorrem se o SQL Server é parado
intencionalmente.
•
Fase 1: Análise Æ A primeira fase é um passagem para a
frente a partir do último checkpoint registado no registo de
transacções. Esta passagem determina e constrói uma
tabela de dirty pages (DPT) constituída por páginas que
poderiam estar “dirty” na altura da falha (ou quando o SQL
Server foi parado). É construída um tabela de transacções
activas que consiste nas transacção que não tinham feito
COMMIT na altura da falha.
•
Fase 2: Refazer Æ Esta fase repete os eventos de forma a
colocar a base de dados no mesmo estado em que estava
na altura da falha. O ponto de início desta fase é o menor
LSN no DPT. O DPT é utilizado para evitar ler páginas que
não necessitam recuperação e evitar escrever alteração não
registadas.
•
Fase 3: Desfazer Æ Esta fase volta para trás do fim do
registo, seguindo as ligações entre entradas no registo para
cada transacção. Qualquer transacção que não tenha feito
COMMIT na altura da falha de sistema é desfeita de forma a
que nenhuma das suas alterações esteja reflectida na base
de dados.
Página 54
Instituto Superior de Engenharia do Porto
Figura 6: Três fases de recuperação do SQL Server
2.3.1)
Locking e Recuperação
O locking, gestão de transacções (rollback ou rollfoward) e
recuperação do sistema estão intimamente ligadas. Uma transacção
pode ser desfeita apenas se todos os dados afectados estavam
bloqueados exclusivamente de forma a que nenhum outro processo
pudesse ver as modificações em progresso (que ainda poderiam ser
desfeitas) ou pudesse ter feito modificações a recursos utilizados
pela transacção que impedissem que fosse desfeita. Apenas uma
transacção activa pode modificar uma linha de cada vez. Isto é a
razão porque os bloqueios exclusivos tem que ser mantidos até que
uma transacção efectue COMMIT ou seja abortada. Até ao momento
em que faz COMMIT, a transacção logicamente não existe. Uma
transacção com nível de isolamento Read Uncommited pode por
vezes ler dados que logicamente nunca existiram uma vez que não
liga à existência de bloqueios exclusivos. Mas quaisquer outras
transacções com um nível de isolamento superior (o que se verifica
por defeito) nunca permitiriam esta situação.
Página 55
Instituto Superior de Engenharia do Porto
2.3.2)
Páginas LSN e Recuperação
Cada página de uma base de dados tem um LSN no cabeçalho da
página que identifica unicamente, por versão, como as linhas de uma
página são modificadas ao longo do tempo. Este LSN de página
reflecte a localização no registo de transacções da última entrada no
registo que modificou dados nesta página. Durante uma operação de
refazer uma transacção, o LSN de cada registo é comparado com o
LSN da página que o registo de transacções modificou; se o LSN é
menor que o LSN do registo, a operação indicada no registo é refeita,
como se vê na Figura 7.
Uma vez que a recuperação encontra o registo do último
checkpoint no registo de transacções (além das transacções que
estavam activas no altura do checkpoint) e processa a partir daí, o
tempo de recuperação é curto e todas as modificações com COMMIT
anteriores ao checkpoint podem ser eliminadas do registo ou
arquivadas. De outra forma, a recuperação demorava muito tempo e
os registos de transacções tornavam-se muito grandes. O registo de
transacções não pode ser limpo para além da primeira transacção
que ainda está em aberto, independentemente de quantos
checkpoints ocorreram subsequentemente. Se uma transacção
permanece em aberto, o registo tem que ser mantido uma vez que
ainda não está claro se completou ou irá alguma vez completar. A
transacção pode necessitar de ser desfeita ou refeita.
Foi notado que alguns registos de transacções não podem ser
limpos para libertar espaço, mesmo após terem sido arquivados. Este
problema resulta com frequência de algum processo ter aberto uma
transacção que depois esqueceu. Por esta razão, do ponto de vista
de desenvolvimento de aplicações, devemos garantir que as
transacções são curtas. Outra razão possível para este problema
relaciona-se com uma tabela ser replicada utilizando replicação
transaccional quando o leitor do registo de replicação não foi
processado ainda. Esta situação é menos comum, uma vez que uma
latência de alguns segundos ocorre enquanto este leitor processa.
Podemos utilizar o DBCC OPENTRAN para localizar a primeira
transacção aberta, ou a última transacção de replicação ainda não
processada e tomar as medida correctivas necessárias (tal como
matar o processo ou executar o stored procedure sp_repldone para
permitir que sejam limpas as transacções de replicação).
Página 56
Instituto Superior de Engenharia do Porto
Figura 7: Comparação do LSN para verificar o processamento da
entrada do registo.
2.4)
O KERNEL DO SQL SERVER E INTERACÇÃO COM O
SISTEMA OPERATIVO
O kernel do SQL Server é responsável pela interacção com o
sistema operativo. É uma simplificação sugerir que o SQL Server tem
um módulo para todas as chamadas ao sistema operativo, mas para
simplificar podemos pensar assim. Todas as chamadas ao sistema
operativo são efectuadas pela API Win32 e pelas bibliotecas run-time
em C. Quando o SQL Server corre sobre uma plataforma Windows
NT/2000, está inteiramente no subsistema Win32 protected. Não são
efectuadas
absolutamente
nenhumas
chamadas
em
Modo
Privilegiado do Windows NT/2000 (Kernel Mode); as chamadas são
feitas em Modo de Utilizador (User Mode). Isto significa que o SQL
Server não pode bloquear todo o sistema, bloquear outros processos
em Modo de Utilizador ou ser bloqueado por estes. Não pode efectuar
chamadas não documentadas ao sistema operativo ou aceder
directamente aos dispositivos (chamadas em driver-level).
Teoricamente se um servidor bloquear com um “écran azul”,
supostamente a culpa seria de um processo em Modo Privilegiado,
por exemplo drivers defeituosos, ou do próprio sistema operativo.
Um dos pontos chave deste produto é a sua capacidade de
escalabilidade, o mesmo se passando com o Windows NT/2000. por
Página 57
Instituto Superior de Engenharia do Porto
este facto, os mesmo ficheiros binários executáveis que são
utilizados num sistema portátil, executam num sistema com
servidores de grande porte e com multiprocessamento simétrico
(SMP). O Windows NT/2000 é a plataforma ideal para o SQL Server
devido ao seu ambiente de 32 bits, seguro e protegido.
Características como escalonamento preemptivo, gestão de memória
virtual paginada, multiprocessamento simétrico e E/S assíncrona são
necessárias para uma boa plataforma de um servidor de bases de
dados. Estas características estão presentes no Windows NT/2000 e
o SQL Server tira partido delas. O SQL Server corre como um único
processo dentro do Windows NT/2000, contendo várias threads de
execução. O sistema operativo encarrega-se de escalonar cada
thread no(s) processador(es) disponível(eis).
2.4.1)
Threading e Multiprocessamento Simétrico
O SQL Server tem uma abordagem diferente para a escalabilidade
com múltiplos processadores do que outros sistemas de bases de
dados
com
capacidade
de
multiprocessamento
simétrico.
Nomeadamente em duas características:
•
Arquitectura com um único processo Æ O SQL Server
tem apenas um processo, com uma arquitectura
multithreaded que reduz a carga (overhead) do sistema e
da memória utilizada. Isto é designado por Symmetric
Server Architecture.
•
Multiprocessamento Nativo em Thread-level Æ O SQL
Server suporta multiprocessamento ao nível da thread em
vez de ao nível de processo, o que permite operações
preemptivas e balanceamento dinâmico de carga sobre
múltiplos processadores. A utilização de múltiplas threads é
mais eficiente do que a utilização de múltiplos processos.
Para se compreender melhor esta estratégia podemos compará-la
com as estratégias utilizadas por outros sistemas. Num sistema sem
threads como algumas variantes do UNIX, um servidor de bases de
dados SMP típico tem vários processos de SGBD, cada um “ligado” a
um processador. Alguns utilizam inclusive um processo por cada
utilizador, o que eleva os custos de memória. Estes processos
utilizam Memória Partilhada para comunicarem, o que mantém a
cache, bloqueios, filas de tarefas, informação de contexto do
utilizador. Os SGBD tem que incluir lógicas complexas que
substituem as funções do sistema operativo: escalonamento de
tarefas do utilizador, simulação de threads, coordenação entre
múltiplos processos, etc. Uma vez que os processos estão ligados a
um processador específico, não existe ou é difícil implementar
Página 58
Instituto Superior de Engenharia do Porto
balanceamento de carga dinâmico. Por questões de portabilidade,
estes sistemas mantém esta abordagem mesmo que corram sobre
um sistema que suporte serviços de threading nativos.
O SQL Server, por outro lado, tem um design com um único
processo e múltiplas threads. As threads são escalonadas nos
processadores por um escalonador em Modo de Utilizador. A Figura 8
mostra as diferenças entre a arquitectura de threading do SQL
Server e outros SGBD típicos.
O SQL Server utiliza sempre várias threads, mesmo num sistema
com um único processador. As threads são criadas e destruídas
dependendo da actividade do sistema, daí que o número de threads
não seja constante. Tipicamente, o número de threads do SQL Server
varia entre 16 e 100, dependendo da actividade e configuração do
sistema. Uma pool de threads controla cada uma das Net-Libraries
que o SQL Server suporta simultaneamente, outra thread controla os
checkpoints da base de dados, outra controla o processo lazywriter e
outra o log writer. Outra thread separada controla actividades de
limpeza de tarefas, como o encolher periódico da base de dados se
no modo de autoshrink. Finalmente, uma pool de threads controla
todos os comandos do utilizador.
Página 59
Instituto Superior de Engenharia do Porto
Figura 8: Design de múltiplas threads num único processo do SQL
Server
2.4.2)
O Worker Thread Pool
Embora pareça que o SQL Server ofereça uma thread separada a
cada utilizador, o sistema é na realidade um pouco mais complexo.
Uma vez que é muito ineficiente manter centenas de threads de
sistema para suportar centenas de utilizadores, o SQL Server
mantém uma pool de worker threads.
Quando um cliente executa um comando, o handler de rede do
SQL Server coloca o comando numa “fila de conclusão” e a próxima
thread livre encarrega-se do comando. Tecnicamente, esta fila é uma
característica do sistema operativo denominada IOCompletion port. A
worker thread aguarda na fila por pedido de rede na IOCompletion
port. Se não existir nenhuma worker thread há espera, o SQL Server
cria uma nova dinamicamente até atingir o valor máximo da
Página 60
Instituto Superior de Engenharia do Porto
configuração de worker threads. O comando do cliente tem que
aguardar por uma worker thread livre.
Mesmo num sistema sobrecarregado com centenas de utilizadores
ligados, a maior parte das threads estão paradas num dado
momento. Quando a carga diminuí o SQL Server encarrega-se de as
eliminar para melhorar o desempenho e libertar memória.
O design do worker thread pool é eficiente para gerir milhares de
utilizadores conectados sem a necessidade de um monitor de
transacções. No entanto, estes componentes são utilizados em
grandes sistemas para atingir níveis de utilizadores activos que o
SQL Server não suporta sem esses componentes extra (por exemplo,
o Microsoft Distributed Transaction Coordinator, Transaction
Processing (TP) Monitor).
Uma thread do serviço worker thread pool serve cada comando
para permitir a utilização completa de múltiplos processadores
enquanto vários comandos de utilizadores estiverem pendentes.
Adicionalmente, um único comando do utilizador sem outras
actividades no servidor pode beneficiar dos múltiplos processadores
se a query for complexa. O SQL Server pode dividir uma query
complexa em várias partes simples e executá-las em paralelo nos
vários processadores. Deve-se notar que este paralelismo só é
possível se existirem processadores livres – ou seja, se o número de
processadores é superior ao número de conexões. Adicionalmente,
este paralelismo não é considerado se o comando não tiver custo de
execução elevado.
Sob o esquema normal de pooling, uma worker thread executa
um pedido do cliente até ao fim. Se uma determinada thread causar
uma falha de paginação, só aquela thread, e por sua vez só aquele
cliente, é bloqueado (Uma falha de paginação ocorre se uma thread
requisita uma página de memória que ainda não foi carregada em
RAM, tendo o gestor de memória virtual do sistema operativo de a
carregar de disco. Este pedido de memória deve esperar um tempo
superior ao tempo normal de acesso a memória uma vez que um I/O
físico é mais custoso do que uma leitura de memória).
Suponhamos algo mais sério do que uma falha de memória.
Suponhamos que durante a execução de um pedido do utilizador,
uma falha do SQL Server é exposta e resulta numa operação ilegal
que provoca uma violação de acesso. O sistema operativo termina
imediatamente a thread causadora. Uma vez que o SQL Server utiliza
a gestão de excepções estruturada do Windows NT/2000, apenas o
utilizador específico do SQL Server que fez o pedido é afectado.
Todos os outros utilizadores ou outras aplicações no sistema não são
afectadas e o sistema operativo não deve bloquear. Claro que na
teoria este sistema é óptimo e não se espera que ocorram estes
Página 61
Instituto Superior de Engenharia do Porto
problemas, mas se ocorrerem é bom que este sistema exista e que
se comporte como é esperado.
2.4.3)
E/S de Disco no Windows NT/2000
O SQL Server 2000 utiliza duas características do Windows
NT/2000 para melhorar a performance de E/S de disco: scattergather I/O e asynchronous I/O.
•
Scatter-gather I/O Æ Este sistema foi introduzido com o
NT 4.0, Service Pack 2. Anteriormente, todos os dados para
uma escrita ou leitura de disco no Windows NT tinham que
estar numa área contígua de memória. Se uma leitura
transferia 64 Kb de dados, o pedido de leitura tinha que
especificar o endereço de uma área de 64 Kb de memória
contínua. O Scatter-gather I/O permite uma escrita ou
leitura de e para áreas descontínuas de memória.
Se o SQL Server ler um extent com 64 Kb, não tem que
alocar uma área única de 64 Kb e depois copiar as páginas
individuais para páginas do buffer cache. Podem alocar oito
páginas de buffer e depois fazer um único scatter-gather I/O
que especifica o endereçamento das oito páginas. O
Windows NT/2000 coloca as oito páginas directamente em
páginas de buffer, eliminando a necessidade do SQL Server
fazer uma cópia de memória separada.
•
Asynchronous I/O Æ Num Asynchronous I/O, após uma
aplicação requisitar uma operação de leitura ou escrita, o
Windows NT/2000 imediatamente devolve o controlo à
aplicação. A aplicação pode então efectuar trabalho adicional
e posteriormente verificar se a escrita ou leitura foi
completada. Por contraste, num Synchronous I/O, o sistema
operativo não devolve o controlo à aplicação até que a
escrita ou leitura acabe. O SQL Server suporta múltiplas
operação concorrentes de Asynchronous I/O sobre cada
ficheiro da base de dados. O número máximo de operação
de I/O para cada ficheiro são determinadas pelos recursos
do sistema, e o SQL Server emite quantas operações forem
possíveis.
Página 62
Instituto Superior de Engenharia do Porto
3. Conclusão
Neste relatório, pretendi estudar e compreender o modo de
funcionamento interno do SQL Server 2000. A abordagem inicial,
pretendeu mostrar que a evolução deste produto está intimamente
ligada aos sistemas operativos da Microsoft e à sua evolução, bem
como às necessidades dos utilizadores de ambos e que foi ainda
influenciada pelas características necessárias em novas áreas de
mercado. A ideia fundamental foi dar-me e a quem ler este relatório
uma perspectiva histórica que situe o produto e que explique os
motivos das suas evoluções/inovações, bem como os momentos em
que ocorreram.
Na segunda, e mais importante, parte deste relatório, descrevemse os principais componentes do SQL Server. Neste momento, posso
dizer que este estudo terá que continuar. A descrição de alguns
componentes pode, e deve, ser mais aprofundada para uma total
compreensão de um sistema tão complexo. Nem eu próprio tinha
uma ideia do que este estudo implicava, quando me decidi abordar
este tema. O conteúdo do relatório foi ainda influenciado pelas
limitações temporais próprias deste tipo de trabalhos e pela
necessidade de simplificação de alguns assuntos, principalmente
quando não focavam directamente os objectivos deste relatório.
Mas o mais importante é que me fez compreender melhor o modo
de funcionamento deste produto e, principalmente, fez-me querer
saber mais.
Não podemos separar o funcionamento interno do SQL Server de
todo um conjunto de factores e funcionalidades que normalmente
são abordados do ponto de vista do programador ou do
administrador. E este funcionamento depende do nível de
conhecimentos nessas áreas para a sua total compreensão.
Espero que quem leia este relatório queira saber mais sobre o
assunto, tal como eu. Considero, se for o caso, que um dos
objectivos deste trabalho foi plenamente atingido.
Página 63
Instituto Superior de Engenharia do Porto
BIBLIOGRAFIA
Livros
“Microsoft SQL Server 2000 - Administrator’s Companion”
Garcia, Reding, Whalen e DeLuca
Microsoft Press
“Inside Microsoft SQL Server 2000”
Kalen Delaney
Microsoft Press
“Microsoft SQL Server 2000 Books Online”
Manuais “Microsoft Official Curriculum”
Curso 2071A
“Querying Microsoft SQL Server 2000 with Transact-SQL”
Curso 2072A
“Administering a Microsoft SQL Server 2000 Database”
Curso 2073A
“Programming a Microsoft SQL Server 2000 Database”
Sites na Internet
SQL Server Magazine – www.sqlmag.com
SQL Server Resources - www.labmice.net/Sql.htm
SQL Zone – www.sql-zone.com
Dblinks.net - www.dblinks.net/Microsoft_Sql_Server/
Microsoft – www.microsoft.com/sql
Definições de Termos Técnicos – www.whatis.com
Página 64
Download

Arquitectura de SQL Server - Departamento de Engenharia