Você está na página 1de 65

114 – Análise das Demonstrações Financeiras | Unidade 01

UNIDADE 2 – ESTRUTURAS DE ARQUIVOS AUXILIARES.

MÓDULO 1 – ÍNDICES (PARTE 1)


01

1 - TÉCNICAS DE PESQUISA
Olá, seja bem-vindo a mais um módulo da nossa disciplina. Iremos estudar agora como os arquivos de
índice auxiliam a localização de informações.

Os arquivos de índice são estruturas adicionais que oferecem atalhos para acessar os dados
solicitados pelos usuários.

A ideia por trás de um índice ordenado é semelhante à que está por trás do índice de palavras usado em
um livro, que lista termos importantes ao final, em ordem alfabética, junto com uma lista dos números
de página onde o termo aparece no livro. Podemos pesquisar o índice do livro em busca de certo termo
em seu interior e encontrar ponteiros de localização (números de página, nesse caso) e usar esses
ponteiros para localizar as páginas especificadas primeiro e depois procurar o termo em cada página
citada.

O mesmo ocorre no uso de índices de arquivos de dados. O índice apontará em qual bloco do disco está
a informação, posteriormente, o gerenciador de arquivos (ou o SGBD) deverá processar o bloco (assim
como buscamos em uma página) procurando pelo conteúdo desejado.

Para o mundo da computação, ponteiros de localização é um número que identifica o início da


posição de determinado objeto em uma unidade de armazenamento, seja ele em memória RAM,
disco ótico ou magnético.

A alternativa, se nenhuma outra indicação for dada, seria folhear lentamente o livro inteiro, palavra por
palavra, para encontrar o termo em que estamos interessados. Isso corresponde a fazer uma pesquisa
linear, que varre o arquivo inteiro. Naturalmente, a maioria dos livros possui informações adicionais,
como títulos de capítulo e seção, que nos ajudam a localizar um termo sem ter de folhear o livro inteiro.
No entanto, o índice é a única indicação exata das páginas onde o termo ocorre no livro. O termo
pesquisa linear é explicado em detalhes logo a seguir.

02

Em se tratando de dados armazenados em tabelas, índices provêm mecanismos para acelerar a


localização dos dados físicos, evitando a leitura de dados desnecessários do disco.

Os índices podem ser constituídos de:

© 2015 - AIEC - Associação Internacional de Educação Continuada

1
114 – Análise das Demonstrações Financeiras | Unidade 01

 Qualquer campo de uma tabela pode servir para criar um índice, como o nome de um
funcionário, o número de CPF dele, a data de cadastro dele na empresa etc. Os índices podem
ser aplicados em praticamente todos os tipos básicos de dados (números inteiros ou
fracionados, caracteres fixos ou variáveis, datas e até mesmo booleano).

 Qualquer parte de um campo de uma tabela. Por exemplo, veremos mais à frente como
índices do tipo hash utilizam parte de um campo string para criar subconjuntos menores de
resultados.

 Um campo pode possuir vários índices, por exemplo, podemos criar um índice de
classificação ascendente e outro de classificação descendente. Ou criar um índice usando a
técnica B-tree e outro usando a técnica de Hash para o mesmo campo.

 Um índice pode ser baseado na união de vários campos, como por exemplo, um índice para
números de telefone que junte os números de código internacional, o código da área e o
número do telefone em si.

Por exemplo, suponha uma tabela de cadastro de funcionário com as informações de ID, nome, estado
civil, idade, sexo, CPF, salário, endereço e telefone. Cada um desses campos poderia possuir um índice
específico, assim, uma pesquisa por qualquer um dos campos ocorreria de maneira mais rápida do que
sem o índice.

Dessa forma, uma tabela pode conter nenhum, um ou vários índices e cada campo da tabela pode
conter nenhum, um ou vários índices. Quando um campo possui mais de um índice, o SGBD é capaz de
escolher aquele mais eficiente (o que retorna o resultado mais rápido).

03

Antes de estudarmos como os índices são construídos, vamos entender como um computador localiza
um registro em um índice.

Os dados armazenados em um sistema de arquivos podem estar registrados de forma aleatória ou de


forma organizada.

Quando estão dispersos (de forma aleatória), para encontrar todas as informações de um conjunto
de dados é necessário testar um a um para saber se é um resultado válido.

Exemplo: suponha que você tem um saco cheio de bolinhas numeradas de 1 a 100. Para encontrar a
bolinha de número 33, você precisa tirar uma a uma e verificar se aquela selecionada é a de número 33,
se não for, tem que procurar outra até encontrar a desejada. Você pode encontrar a de número 33 na
primeira bolinha que você tirar do saco, mas também pode ser na última bolinha. Dessa forma,

© 2015 - AIEC - Associação Internacional de Educação Continuada

2
114 – Análise das Demonstrações Financeiras | Unidade 01

estatisticamente falando, o número médio de operações de consulta que você precisa fazer para
encontrar determinada bolinha é de 50% do tamanho do seu conjunto, nesse caso, 50 operações.

Se você possui um conjunto ordenado de valores ou se você possui um índice ordenado que aponta
para seu conjunto de dados disperso, há várias técnicas que farão o número de operações de consulta
diminuir em muito.

Uma dessas técnicas (sem dúvida a mais usada em índices de banco de dados) é a técnica de B-Tree, que
será apresentada a seguir.

04

1.1 - B-Tree (Árvore Binária)

A técnica de B-tree (árvore binária) é uma forma de pesquisa de dados otimizada.

A ideia por trás da técnica B-tree é dividir o conjunto de dados alvo em duas partes, e realizar o teste
de validade no valor do meio do conjunto:

 se o valor for encontrado, retorna-se esse valor;

 se o valor desejado for menor do que o encontrado, despreza-se o conjunto superior e realiza
nova operação no outro conjunto;

 se o valor desejado por maior do que o encontrado, despreza-se o conjunto anterior e realiza
nova operação no outro conjunto.

Veja a seguir um exemplo de como o algoritmo B-tree trabalha para localizar a bolinha número 33 em
um conjunto de bolinhas de 1 a 100.

05

Problema: localizar a bolinha número 33 em um conjunto de bolinhas de 1 a 100.

© 2015 - AIEC - Associação Internacional de Educação Continuada

3
114 – Análise das Demonstrações Financeiras | Unidade 01

© 2015 - AIEC - Associação Internacional de Educação Continuada

4
114 – Análise das Demonstrações Financeiras | Unidade 01

06

Vamos ver graficamente como seria essa representação:

Planilha Excel com resultados da pesquisa.


Desprezamos os números de 58 a 100 por motivos de espaço da tela.

© 2015 - AIEC - Associação Internacional de Educação Continuada

5
114 – Análise das Demonstrações Financeiras | Unidade 01

07

A fórmula matemática que retorna o número máximo de operações necessárias para localizar um item
usando a técnica de árvore binária é Log2 X, sendo X o número de elementos do conjunto. No nosso
exemplo Log2 100 = 6,64. Ou seja, qualquer elemento é encontrado em no máximo 6 operações de
consulta.

Para calcular um valor logaritmo sem possuir uma calculadora, basta abrir o Google e na barra de
pesquisa de sites digite “log2 100” e pressione Enter, você verá que o Google já irá calcular o valor
para você e lhe apresentar o resultado esperado.

Tela do Google com o cálculo logaritmo.

08

1.2 - Índice Hash

A técnica de hash tem por objetivo separar um grande conjunto em conjuntos menores, dessa forma,
uma pesquisa linear posterior pode ser feita com maior performance.

Essa técnica é indicada para campos grandes onde um índice b-tree geraria um arquivo muito grande.

Vamos ver um exemplo. Suponha que tenhamos uma tabela para cadastro de Boletos Bancários. Os
campos mais comuns de um boleto bancário são:

 Número do código de barras (geralmente com 44 caracteres),

 data de vencimento e

 valor.

© 2015 - AIEC - Associação Internacional de Educação Continuada

6
114 – Análise das Demonstrações Financeiras | Unidade 01

Se fôssemos criar um índice b-tree para o campo de código de barras, esse arquivo teria 44 bytes para o
registro do número do código de barras e mais 8 bytes para a localização do bloco. Perceba que cada
registro precisa de 52 bytes. Uma linha de registro da tabela de boletos bancários possui 4 bytes para a
chave primária, 44 bytes para o código de barras, 4 bytes para a data de vencimento e 4 bytes para o
valor, totalizando 56 bytes. Veja que o tamanho do índice (52 bytes por linha) é praticamente o mesmo
tamanho do registro da tabela (56 bytes por linha). Assim, o uso do índice pode não ser tão eficiente
quanto o desejado, pois uma pesquisa teria que varrer um arquivo muito grande.

É nesse contexto que entra a ideia do índice hash. Ao invés de ter apenas um arquivo de índice
grande, o algoritmo do hash identifica uma forma de quebrar esse arquivo em vários arquivos de
índice menores. Dessa forma, a pesquisa é feita em um arquivo pequeno.

Veja a seguir como isso é feito.

09

Para quebrar o arquivo, o algoritmo de hash usa, geralmente, o último caractere do campo indexado.

 Se é um campo de números, ele quebra em 10 arquivos (um, para números terminados em 0,


outro, para terminados em 1, e assim por diante);

 se é um campo de texto, ele quebra em 26 arquivos, um para cada letra (um para textos
terminados em A, outro para textos terminados em B, e assim por diante).

Vejamos um exemplo: para o contexto acima, onde o campo de indexação do código de barras contém
44 caracteres numéricos, o algoritmo de hash pode criar 10 arquivos, usando o último dígito do código
de barras para separar os arquivos. Um arquivo terá os números de código de barras que terminam em
0, outro terá os números terminados em 1, outro em 2, e assim por diante, até o último arquivo com
códigos que terminam em 9. Dessa forma, ao pesquisar um determinado número de código de barras,
por exemplo, 12389712738912878192873928718298738982198273283, será usado o arquivo que
contém apenas códigos de barra terminados em 3. Com isso, a pesquisa teoricamente será dez vezes
mais rápida do que se executasse em um único arquivo.

Algoritmos de hash modernos usam a funcionalidade de checksum para determinar um valor


numérico inteiro (4 bytes) para qualquer tipo de string ou número indexado. Dessa forma, ele pode
quebrar o arquivo de índice em arquivos ainda menores, e de modo padronizado, de tal forma que a
performance de pesquisa fique ainda mais rápida. A funcionalidade de checksum efetua uma
operação de comparação binária, similar ao que usamos no cálculo de dígito verificador, gerando um
número inteiro como resultado da operação. Para cada número gerado, um índice específico pode ser
criado.

© 2015 - AIEC - Associação Internacional de Educação Continuada

7
114 – Análise das Demonstrações Financeiras | Unidade 01

10

1.3 - Pesquisa linear

Quando um índice não existe e uma pesquisa é solicitada a um determinado campo de uma tabela,
normalmente ocorre o que denominamos de pesquisa linear.

A pesquisa linear nada mais é do que a avaliação um a um de cada registro, a fim de se identificar se
aquele registro satisfaz ou não a condição da pesquisa.

Vamos a mais um exemplo. Suponha que pesquisemos por “josé” na tabela de funcionários (campo
nome). Se houver um índice para nomes, o SGBD irá processar a consulta no índice, e este retornará a
posição de todos os registros que contenham “josé” no nome. Daí o SGBD coleta os demais dados
solicitados nas posições fornecidas pelo índice e retorna os dados para o usuário.

Já sem o índice, o SGBD testará um a um todos os funcionários cadastrados; para cada elemento
testado, em caso positivo, ele coleta os dados solicitados, em caso negativo, ignora e vai para o próximo
registro. Certamente, essa segunda opção demora muito mais (veremos um exemplo logo a seguir
quando explicarmos a técnica de árvore binária).

Muitos SGBDs são capazes de criar índices automaticamente, à medida que pesquisas lineares vão
acontecendo no banco de dados, dessa forma, o SGBD consegue gerar uma otimização automática de
acesso a dados. Por vezes, ao momento do projeto do sistema, é possível já definir quais serão os
índices criados. Normalmente criam-se índices para chaves primárias e estrangeiras e todos os
demais campos pesquisáveis do sistema de informação. Algumas operações, como a operação LIKE,
não são possíveis de usar índices; nesses casos, uma pesquisa linear é obrigatória.

11

2 - ÍNDICES, BLOCOS E SETORES DE DISCO


Os setores do disco rígido são agrupados em blocos lógicos no momento da formatação dos discos.
Esses blocos podem assumir diversos tamanhos, sendo que 2Kb a 512Kbytes é uma faixa comum para a
maioria dos sistemas de arquivos (NTFS, ext3, e outros). Quando uma cabeça magnética lê um disco, ela
não lê um bit ou byte isoladamente, mas ela lê blocos de cada vez.

Um bloco pode conter vários arquivos pequenos, da mesma forma, um arquivo muito grande precisará
de vários blocos para ter seu conteúdo registrado. Dessa forma, há dois comportamentos possíveis:

 Quando um bloco possui vários arquivos, o gerenciador de dados lê o bloco inteiro e despreza
os dados não necessários. Exemplo.

© 2015 - AIEC - Associação Internacional de Educação Continuada

8
114 – Análise das Demonstrações Financeiras | Unidade 01

 Quando um arquivo é maior que o espaço de um bloco, cada bloco que recebe o conteúdo do
arquivo possui um ponteiro para o próximo bloco de conteúdo, dessa forma, os blocos são
encadeados para receber o arquivo. Veja um exemplo.

Exemplo

Para ler o arquivo A1 que está no bloco B1, o gerenciador lê todo o bloco B1 que também contém os
arquivos A2, A3, a4. Então o gerenciador despreza esses arquivos, enviando para a memória RAM
apenas o arquivo A1

Veja um exemplo

Para ler o arquivo A1 que está no bloco B1, o gerenciador lê todo o bloco B1, ao final, ele percebe que
há um ponteiro informando que o conteúdo continua no bloco B2, então ele lê o conteúdo do bloco
B2 também; ainda, ao final deste, o gerenciador encontra outro ponteiro informando que continua no
bloco B3, consequentemente ele lê o bloco B3. Neste último bloco ele encontra um indicativo de final
do arquivo, então ele encerra a leitura de blocos e envia o conteúdo para a memória RAM.

12

Os arquivos de índices podem apontar para setores ou blocos, sendo esse segundo o mais comum.
Nesse tipo de técnica, o gerenciador de arquivos irá ler todo o bloco, desprezando as informações
desnecessárias.

Exemplo: Suponha que o índice informe ao gerenciador de discos que a informação solicitada pelo
usuário está no bloco B1, então o gerenciador informa à cabeça magnética para ler o bloco B1. Ao ler
esse bloco, o gerenciador de disco percebe que além dos dados solicitados pelo usuário, há outros
dados presentes. Esses outros dados são então desprezados e apenas o conteúdo solicitado é
encaminhado à memória RAM.

Ao estudar índices vamos perceber duas possibilidades:

a) de um bloco com mais informação do que o necessário (cujas demais são desprezadas) e

b) de informações que estão espalhadas em vários blocos, usando ponteiros no final de cada bloco,
que indica qual é o bloco subsequente (onde os blocos complementares serão lidos
automaticamente até carregar toda a informação).

O gerenciador de disco é o responsável por colher as informações desejadas e desprezar as demais.

13

© 2015 - AIEC - Associação Internacional de Educação Continuada

9
114 – Análise das Demonstrações Financeiras | Unidade 01

3 - TIPOS DE ÍNDICES ORDENADOS DE ÚNICO NÍVEL


Para uma tabela de dados com determinada estrutura de registro consistindo em vários campos, um
índice normalmente é definido em um único campo da tabela, chamado campo de índice (ou atributo de
indexação). O índice costuma armazenar cada valor do campo de índice junto com uma lista de
ponteiros para todos os blocos de disco que contêm registros com esse valor de campo.

Os valores no índice são ordenados de modo que possamos realizar uma pesquisa binária no índice:
verdadeiro se satisfaz a condição de pesquisa ou falso se não satisfaz. Se tanto o arquivo de dados
quanto o arquivo de índice estiverem ordenados, e visto que este normalmente é muito menor do que o
arquivo de dados, a procura no índice que usa pesquisa binária é uma opção mais eficiente (já vimos
anteriormente que o algoritmo de árvore binária é capaz de localizar valores com extrema eficiência).

Existem vários tipos de índices ordenados. Um índice primário é especificado no campo de chave de
ordenação de um arquivo ordenado de registros (chave primária). Lembre-se que um campo de chave
de ordenação é usado para ordenar fisicamente os registros de arquivo no disco, e cada registro tem
um valor único para esse campo. Veja este exemplo.

Se o campo de ordenação não for um campo de valor exclusivo (único), ou seja, se diversos registros no
arquivo puderem ter o mesmo valor para o campo de ordenação, outro tipo de índice, chamado índice
de agrupamento (clustering), pode ser utilizado.

Observe que um arquivo pode ter apenas um campo de ordenação


física, de modo que pode ter apenas um índice primário ou um índice
de agrupamento, mas não ambos.

Um terceiro tipo de índice, chamado índice secundário, pode ser especificado em qualquer campo de
uma tabela. Um arquivo de dados pode ter vários índices secundários além de seu método de acesso
primário. Vamos estudar agora os tipos de índices e calcular o número de operações que eles levam
para encontrar os resultados.

Veja este exemplo

Por exemplo, suponha que uma tabela FUNCIONÁRIO, possua os campos ID_Funcionário, Nome, CPF
e Data_Nascimento. Se a chave primária for ID_Funcionário, os registros serão fisicamente
armazenados na sequência do ID_Funcionário (exemplo: 1 – Marcelo, 2 – Ana, 3 – Cláudio, ...). Se a
chave primária for Nome, os registros serão fisicamente armazenados na sequência alfabética
(exemplo: 2- Ana, 3 – Cláudio, 1 – Marcelo, ...). Perceba que nessa segunda forma, toda vez que um
novo funcionário é cadastrado na tabela, a tabela precisa ser reorganizada alfabeticamente para
satisfazer a condição de índice primário. O mesmo aconteceria se a chave primária fosse baseada no
CPF do funcionário, os registros precisariam ser reordenados sempre que inserções ou alterações

© 2015 - AIEC - Associação Internacional de Educação Continuada

10
114 – Análise das Demonstrações Financeiras | Unidade 01

surgissem. Já quando utilizamos como chave primária um número sequencial, sempre um novo
elemento é agregado ao final da tabela, evitando a reordenação dos demais dados.

14

3.1 - Índice primário

Um índice primário, também chamado de índice de chave primária, é um arquivo ordenado cujos
registros são de tamanho fixo com dois campos, e ele atua como uma estrutura de acesso para
procurar e acessar de modo eficiente os registros de dados de uma tabela em um arquivo de banco
de dados.

O primeiro campo é do mesmo tipo de dado do campo de chave de ordenação do arquivo de dados, e o
segundo campo é um ponteiro para um bloco de disco (um endereço de bloco) onde os dados do
registro estão localizados.

Existe uma entrada de índice no arquivo de índice para cada bloco no arquivo de dados. Cada entrada
de índice tem o valor do campo de chave primária para o primeiro registro em um bloco e um ponteiro
para esse bloco com seus dois valores de campo. Para criar um índice primário no arquivo ordenado,
usamos o campo Nome como chave primária, pois esse é o campo de chave de ordenação do arquivo
(supondo que cada valor de Nome seja exclusivo). Cada entrada no índice tem um valor de Nome e um
ponteiro. As três primeiras entradas de índice são as seguintes: Aila Gomes, 1022; Ana Botafogo, 4094;
Ana Lúcia Costa, 3018. Cada um desses números representa a localização física no disco rígido dos
blocos onde esses dados estão localizados. Assim, por exemplo, os dados da Aila Gomes estão
localizados a partir do bloco 1022 do disco rígido.

Nome Localização

Aila Gomes 1022

Ana Botafogo 4096

Ana Lúcia Costa 3018

Beatriz Nogueira 223

Cristina Almeira Rocha 1022

Denilson Xavier Alcântara 4056

... ...

Exemplo de tabela de índices primários

© 2015 - AIEC - Associação Internacional de Educação Continuada

11
114 – Análise das Demonstrações Financeiras | Unidade 01

Observe no exemplo acima a localização dos funcionários de nome Aila e Cristina. Perceba que ambos os
ponteiros de índices apontam para o mesmo número de bloco: 1022. Isso significa que neste bloco há
mais de um registro de informação, ou seja, o tamanho do bloco é suficientemente grande para
comportar mais de um registro de dados. Conforme já explicado, quando ocorrer uma consulta, o SGBD
irá procurar dentro do bloco as informações desejadas e desprezar as demais.

15

O arquivo de índice para um índice ocupa um espaço muito menor do que o arquivo de dados, por dois
motivos.

 Primeiro, existem menos entradas de índice do que registros no arquivo de dados.

 Segundo, cada entrada de índice normalmente é menor em tamanho do que um registro de


dados, pois tem apenas dois campos; em consequência, mais entradas de índice do que
registros de dados podem caber em um bloco.

Assim, uma pesquisa no arquivo de índice requer menos acessos de bloco do que uma pesquisa no
arquivo de dados.

Para recuperar um registro, dado o valor de seu campo de chave primária, realizamos uma pesquisa no
arquivo de índice para encontrar a entrada de índice apropriada, e depois recuperamos o bloco do
arquivo de dados cujo endereço consta no arquivo de índice.

O exemplo a seguir ilustra a economia em acessos a bloco que pode ser alcançada quando um índice
primário é utilizado para procurar um registro.

16

Exemplo:

Suponha que tenhamos um arquivo ordenado com 30.000 registros armazenados em um disco com
tamanho de bloco igual a 1.024 bytes. Os registros de arquivo são de tamanho fixo e não espalhados,
com tamanho de registro de 100 bytes, ou seja, cada bloco contém 1.024/100 = 10 registros por bloco.
O número de blocos necessários para armazenar todos os registros é 30.000 / 10 = 3.000 blocos. Uma
pesquisa binária no arquivo de dados precisaria de aproximadamente Log2 3.000 = 12 acessos. Ou seja,
aplicando a técnica de B-tree, qualquer registro poderia ser localizado em no máximo 12 testes lógicos.

Agora, suponha que o campo de chave de ordenação do arquivo seja de 9 bytes de extensão, um
ponteiro de bloco possua 6 bytes de extensão e que tenhamos construído um índice primário para o
arquivo. O tamanho de cada entrada de índice é de (9 + 6) 15 bytes. O fator de bloco para o índice é
1.024/15 = 68 entradas por bloco. O número total de entradas de índice r, é igual ao número de blocos
no arquivo de dados, que é 3.000. O número de blocos de índice é, portanto, 3.000 / 68 = 45 blocos.
Para realizar uma pesquisa binária no arquivo de índice, seriam necessários apenas Log2 45 = 6 acessos

© 2015 - AIEC - Associação Internacional de Educação Continuada

12
114 – Análise das Demonstrações Financeiras | Unidade 01

de bloco. Assim, para procurar um registro usando o índice, precisamos de um acesso de bloco adicional
ao arquivo de dados, para um total de 6 + 1 = 7 acessos de bloco — uma melhoria em relação à pesquisa
binária no arquivo de dados, que exigiu 12 acessos a bloco de disco.

Um problema importante com índice primário — assim como com qualquer


arquivo ordenado — é a inserção e exclusão de registros. Com um índice
primário, o problema é aumentado porque ao se tentar inserir um registro em
sua posição correta no arquivo de dados, é preciso não apenas mover
registros para criar espaço para o novo registro, mas também mudar algumas
entradas de índice, pois a movimentação de registros mudará os registros de
endereços de alguns blocos. A exclusão de registro é tratada com marcadores
de exclusão.

A reconstrução de índices pode ser automática ou manual. O tempo de reconstrução pode ser quase
instantâneo ou levar muitos minutos.

17

3.1.1 - Índice Denso x Índice Esparso

Os índices também podem ser caracterizados como densos ou esparsos.

Um índice denso tem uma entrada de índice para cada valor de chave de pesquisa (e, portanto, cada
registro) no arquivo de dados (exatamente como no exemplo anterior).

Um índice esparso (ou não denso), por sua vez, tem entradas de índice para somente alguns dos
valores de pesquisa. Um índice esparso tem menos entradas do que o número de registros no
arquivo.

Veja graficamente como seriam representados:

© 2015 - AIEC - Associação Internacional de Educação Continuada

13
114 – Análise das Demonstrações Financeiras | Unidade 01

Um índice denso possui uma entrada no arquivo


Um índice esparso possui apenas alguns
de índices para cada registro no arquivo de dados.
registros de dados no índice.

Observe no exemplo acima que o índice criado possui entradas que apontam somente para alguns
valores. Para que o SGBD localize, por exemplo, o conteúdo do registro 60, ele precisa ler o bloco inteiro
apontado pelo índice 50 e desprezar o valor deste registro. Usando a técnica b-tree, é possível
identificar qual bloco contém o registro desejado. Após localizar esse primeiro nome, o SGBD precisa
processar as demais entradas linearmente até localizar o registro desejado.

18

Abaixo apresentamos um resumo comparativo entre índices densos e esparsos:

Índice Denso Índice Esparso

Vantagens:
Vantagem:
 Ocupa menos espaço.
 É mais rápido que o índice esparso.  É mais rápido do que não utilizar nenhum
índice.

Desvantagem: Desvantagem:

 Ocupa mais espaço.  É mais lento que o índice denso.

19

3.2 - Índices de agrupamento

Se os registros de arquivo forem fisicamente ordenados em um campo não chave (que não tem um
valor distinto para cada registro, aceitando, portanto, dados duplicados) esse campo é chamado de

© 2015 - AIEC - Associação Internacional de Educação Continuada

14
114 – Análise das Demonstrações Financeiras | Unidade 01

campo de agrupamento, e o arquivo de dados é chamado de arquivo agrupado. Podemos criar um tipo
de índice diferente, chamado índice de agrupamento, para agilizar a recuperação de todos os registros
que têm o mesmo valor para o campo de agrupamento.

Isso difere de um índice primário, que exige que o campo de ordenação do arquivo de dados tenha um
valor distinto para cada registro.

Ou seja, em uma tabela que tem um campo (coluna) com valores únicos, exclusivos e não repetidos
então essa coluna pode possuir um índice primário. Por outro lado, se esse campo possuir valores que
podem se repetir, então esse campo só pode possuir um índice do tipo agrupamento.

A principal diferença entre um e outro é que para um valor de pesquisa em um índice primário, a
resposta será sempre zero ou um registro; já para um índice de agrupamento, a resposta para a
pesquisa poderá ser zero, um ou mesmo vários registros. Resumindo, se o campo é do tipo RESTRICT
ou UNIQUE (que não aceita valores repetidos), então se aplica um índice primário, do contrário,
aplica-se um índice de agrupamento.

Posteriormente vamos ver os padrões SQL para a criação de índices (que já foram superficialmente
vistos na matéria Banco de dados I).

Assim como em um índice primário, um índice de agrupamento também é um arquivo ordenado com
dois campos; o primeiro campo é do mesmo tipo do campo de agrupamento do arquivo de dados, e o
segundo campo é um ponteiro de bloco de disco. Há uma entrada no índice de agrupamento para cada
valor distinto do campo de agrupamento, e ele contém o valor e um ponteiro para o primeiro bloco no
arquivo de dados que tem um registro com esse valor para seu campo de agrupamento.

20

Observe com atenção: ele não aponta diretamente para o SETOR específico onde está o registro
identificado, mas sim para o BLOCO onde está o registro. Dessa forma, depois que se saber o bloco onde
está a informação, é necessário que o SGBD processe o bloco até localizar o registro em si.

Vejamos um exemplo, suponha uma tabela hipotética que possua o nome, o sobrenome e outros de um
funcionário.

A título de exemplo, a primeira coluna que apresentamos abaixo NÃO é a chave primária, mas sim o
bloco onde se encontram armazenados os registros de cada funcionário:

Bloco físico do Demais campos


Nome Sobrenome
disco da tabela...

1 André Costa ....

© 2015 - AIEC - Associação Internacional de Educação Continuada

15
114 – Análise das Demonstrações Financeiras | Unidade 01

André Barros Leite ...

André Matias Lemos ...

Bernardo Felix Coelho ...

Caio Ferreira Leite ...

Caio Gomes da Costa ...


2
Daniel Matos Lemos ...

Daniel Costa ...

Eduardo Martins ...

Fábio Lemos Maia ...


3
Felipe César ...

Mauro Benvindo ...

Mauro Lemos ...

Miriam Felix Coelho ...


4
Miriam Ferreira Leite ...

Paulo Gomes da Costa ...

Tabela que inclui uma referência do bloco físico no qual se encontra cada registro

21

Agora vamos entender como um índice de agrupamento para o campo NOME (que não é exclusivo) é
criado para essa tabela:

Nome Bloco físico do disco

André 1

Bernardo 1

Caio 2

Daniel 2

Eduardo 3

© 2015 - AIEC - Associação Internacional de Educação Continuada

16
114 – Análise das Demonstrações Financeiras | Unidade 01

Fábio 3

Felipe 3

Mauro 3

Miriam 4

Paulo 4

Índice de agrupamento para o campo NOME

Observe que o índice aponta somente para o bloco do primeiro valor encontrado na tabela. E não para a
posição exata do setor de onde a informação deve ser lida. Isso, conforme já explicado, se dá ao fato de
que a cabeça magnética só consegue ler blocos de cada vez, ela não lê apenas bytes isolados. Dessa
forma, ao ler um bloco, o SQBD precisa desprezar os demais dados que não lhe interessam.

Vejamos um exemplo a seguir.

22

Exemplo:

Ao solicitar todas as informações do funcionário André (SELECT * FROM FUNCIONARIOS WHERE NOME =
“André”):

Então ele iria ler


de uma só vez as
Então o SGBD iria
informações
O SGBD iria desprezar as
contidas no
primeiro informações do
A partir do bloco 1, que
identificar em Bernardo e iria
índice, ele consequentemen
qual bloco estão retornar para o
identificaria que te são as
as informações usuário as
é no bloco de informações de
do(s) informações dos
número 1. três funcionários
funcionário(s) de três funcionários
de nome André e
nome André. de nome André
de um
encontrados.
funcionário de
nome Bernardo.

Um detalhe importante a ser citado é que pelo fato de ele ter encontrado um funcionário de nome
diferente no mesmo bloco, ele já sabe que não existem outros funcionários de nome André em outros
blocos, pois a existência do Bernardo dentro do mesmo bloco é suficiente para sinalizar que há somente
três funcionários de nome André.

© 2015 - AIEC - Associação Internacional de Educação Continuada

17
114 – Análise das Demonstrações Financeiras | Unidade 01

Resumindo em um passo a passo, o SGBD se comporta assim:

1) Há um funcionário de nome “André” no índice?

2) Sim, há, os dados dela estão no bloco 1.

3) Leia todo o bloco 1.

4) O primeiro funcionário chama-se “André”?

5) Sim, então mantenha os dados dele em memória (André Costa).

6) O próximo funcionário chama-se “André”?

7) Sim, então mantenha os dados dele em memória (André Barros Leite).

8) O próximo funcionário chama-se “André”?

9) Sim, então mantenha os dados dele em memória (André Matias Lemos).

10) O próximo funcionário chama-se “André”?

11) Não, então despreze os demais dados do bloco.

12) Retorne os dados mantidos em memória para o usuário.

23

Vamos agora a outro exemplo, no qual o nome do funcionário pesquisado está em dois blocos.

Ao solicitar todas as informações do funcionário Mauro (SELECT * FROM FUNCIONARIOS WHERE NOME
= “Mauro”):

• O SGBD iria primeiro identificar em qual bloco estão as informações do(s) funcionário(s) de
nome Mauro.

• A partir do índice, ele identificaria que é no bloco de número 3.

• Ele iria ler de uma só vez as informações contidas no bloco 3, que consequentemente são as
informações de quatro funcionários de nome Eduardo, Fábio, Felipe e Mauro.

• O SGBD iria desprezar as informações dos três primeiros, mas antes de retornar os dados do
funcionário de nome “Mauro”, sobrenome “Benvindo”, como se chegou ao fim do bloco com
um valor verdadeiro para o resultado solicitado, o SGBD testaria o próximo bloco para saber se
há outros funcionários de nome “Mauro” na sequência.

© 2015 - AIEC - Associação Internacional de Educação Continuada

18
114 – Análise das Demonstrações Financeiras | Unidade 01

• Como no bloco 4 há outro funcionário de nome “Mauro” (sobrenome “Lemos”), o SGBD


continua agregando os dados desse funcionário até encontrar um funcionário de nome
diferente (no caso é a funcionário de nome “Miriam”), desprezando os demais dados
encontrados e concluindo assim a seleção de dados e retornando os dados ao usuário.

Resumindo em um passo a passo, o SGBD se comporta assim:

1) Há um funcionário de nome “Mauro” no índice?

2) Sim, há, os dados dela estão no bloco 3.

3) Leia todo o bloco 3.

4) O primeiro funcionário chama-se “Mauro”?

5) Não, então despreze os dados dele (Eduardo Martins).

6) O próximo funcionário chama-se “Mauro”?

7) Não, então despreze os dados dele (Fábio Lemos Maia).

8) O próximo funcionário chama-se “Mauro”?

9) Não, então despreze os dados dele (Felipe César).

10) O próximo funcionário chama-se “Mauro”?

11) Sim, então mantenha os dados dele em memória (Mauro Benvindo).

12) Chegamos ao fim do bloco, então leia o próximo bloco (bloco 4).

13) O primeiro funcionário desse bloco chama-se “Mauro”?

14) Sim, então mantenha os dados dele em memória (Mauro Lemos).

15) O próximo funcionário chama-se “Mauro”?

16) Não, então despreze os demais dados do bloco.

17) Retorne os dados mantidos em memória para o usuário.

Alguns registros podem ser tão grandes que cada um deles ocupa mais de um
bloco; dessa forma, o SGBD também é capaz de ler blocos em sequência
recuperando todos os blocos com informações desejadas pelo usuário. Por
exemplo, os dados completos de um único funcionário poderiam estar em 5
blocos.

© 2015 - AIEC - Associação Internacional de Educação Continuada

19
114 – Análise das Demonstrações Financeiras | Unidade 01

Concluindo, o SGBD processa bloco por bloco e despreza as informações lidas que não são de interesse
do usuário.

24

3.2.1 - Inserção e Exclusão de registros

Observe que a inserção e exclusão de registro causam problemas, pois os registros de dados estão
fisicamente ordenados. Ao excluir ou inserir um registro seria necessário recriar toda a tabela
novamente, reorganizando os dados, bem como recriar o índice a cada operação.

Em tabelas com muitos registros e com muitas inserções e exclusões, isso poderia impactar fortemente
na performance do banco de dados. Imagine, por exemplo, um cenário de uma tabela com 100.000
registros, com 100 operações de inserção e exclusão de dados por segundo Certamente seria
catastrófico para SGBD ter que reorganizar a tabela de dados 100 vezes por segundo com cerca de
100.000 registros sendo movimentados em cada operação.

Para aliviar o problema de inserção, é comum reservar um bloco inteiro (ou um Cluster de blocos
contínuos) para cada valor do campo de agrupamento dentro do arquivo da tabela; todos os registros
com esse valor são colocados no bloco (ou cluster de bloco). Isso cria espaços em branco na tabela de
forma que a inserção e exclusão tornam-se relativamente mais simples. Para as exclusões, basta
desprezar os espaços ocupados, para as inserções, há espaços dentro do bloco (ou cluster), quando
esse espaço é totalmente ocupado, um novo bloco é endereçado como continuidade do anterior.

Vamos ver a seguir alguns exemplos.

25

Para a tabela de funcionários que vimos anteriormente, ao reservar espaços de bloco, teríamos a
seguinte estrutura:

Bloco físico do Nome Sobrenome Demais campos da


disco tabela...

André Costa ....

André Barros Leite ...


1
André Matias Lemos ...

(espaço disponível)

2 Bernardo Felix Coelho ...

© 2015 - AIEC - Associação Internacional de Educação Continuada

20
114 – Análise das Demonstrações Financeiras | Unidade 01

(espaço disponível)

(espaço disponível)

(espaço disponível)

Caio Ferreira Leite ...

Caio Gomes da Costa ...


3
(espaço disponível)

(espaço disponível)

Daniel Matos Lemos ...

Daniel Costa ...


4
...

...

Demais blocos... ... ... ...

Reserva de blocos

Observe na imagem acima que cada nome ocupa o espaço de um bloco, os espaços não utilizados ficam
reservados para operações de inserção. Como consequência direta, observe que o número de blocos
aumenta muito, ocupando mais espaço em disco. Dessa forma, o ganho que conseguimos nas operações
de inserção tem como fator negativo ocupar um espaço em disco muito maior.

26

Vamos ver dois exemplos de inserção.

Exemplo 1 - Suponha que desejamos inserir um registro de nome “André Peixoto”. Como o SGBD irá
processar essa operação? De maneira bem simples, irá localizar o espaço disponível no fim do primeiro
bloco e lá cadastrar esse registro. Observe agora que o primeiro bloco ficaria totalmente ocupado, sem
espaços disponíveis.

Exemplo 2 - E se agora outro registro de nome “André Xavier” fosse inserido? Como o SGBD iria se
comportar? Preste atenção no passo a passo abaixo, pois o SGBD iria alocar um novo bloco para incluir
esse funcionário:

1) Ao tentar inserir o “André Xavier”, o SGBD iria localizar na tabela de índices qual é o bloco para
o nome “André”, identificando ser o bloco 1.

2) Ao varrer o bloco 1, o SGBD iria perceber que não há espaço disponível para esse bloco.

© 2015 - AIEC - Associação Internacional de Educação Continuada

21
114 – Análise das Demonstrações Financeiras | Unidade 01

3) Então o SGBD iria alocar outro bloco dentro do arquivo (provavelmente aumentando o tamanho
físico do arquivo).

4) Após criar o novo bloco, o SGBD irá criar um ponteiro no final do bloco 1 apontando para esse
novo bloco.

5) Depois irá inserir o “André Xavier” nesse novo bloco.

Observe que o SGBD cria ponteiros que direcionam o final de um bloco para o início do outro bloco a fim
de prover mais espaço de armazenamento. Dessa forma, o resultado final serial algo como:

Bloco físico do disco Nome Sobrenome Demais campos da


tabela...

André Costa ....

André Barros Leite ...

1 André Matias Lemos ...

André Peixoto

Ponteiro: Continua no bloco 50.

Bernardo Felix Coelho ...

(espaço disponível)
2
(espaço disponível)

(espaço disponível)

Caio Ferreira Leite ...

Caio Gomes da Costa ...


3
(espaço disponível)

(espaço disponível)

Daniel Matos Lemos ...

Daniel Costa ...


4
...

...

Demais blocos... ... ... ...

© 2015 - AIEC - Associação Internacional de Educação Continuada

22
114 – Análise das Demonstrações Financeiras | Unidade 01

50 André Xavier ...

(espaço disponível)

(espaço disponível)

(espaço disponível)

Tabela após a inserção de um novo bloco e de dois registros, destacados em amarelo.

27

3.3 - Índices secundários

Um índice secundário oferece um meio secundário para acessar um arquivo de dados para o qual
algum acesso primário já existe. Os registros do arquivo de dados poderiam ser ordenados ou
desordenados.

O índice secundário pode ser criado em um campo que é uma chave candidata e tem um valor único em
cada registro, ou em um campo não chave com valores duplicados. O índice é novamente um arquivo
ordenado com dois campos. O primeiro campo é do mesmo tipo de dado do campo a ser indexado do
arquivo de dados. O segundo campo é um ponteiro de bloco ou um ponteiro de registro. Muitos índices
secundários (e, portanto, campos de indexação) podem ser criados para o mesmo arquivo — cada um
representa um meio adicional de acessar esse arquivo com base em algum campo específico.

Primeiro, consideramos uma estrutura de acesso de índice secundário em um campo de chave (único)
que tem um valor distinto para cada registro. Tal campo às vezes é chamado de chave secundária. No
modelo relacional, isso corresponderia a qualquer atributo de chave UNIQUE ou ao atributo de chave
primária de uma tabela.

Nesse caso, existe uma entrada de índice para cada registro no arquivo de dados, que contém o valor do
campo para o registro e um ponteiro para o bloco em que o registro está armazenado ou para o próprio
registro. Logo, tal índice é denso.

28

Um exemplo de como poderíamos ter os dados organizados em um índice secundário seria o que vemos
a seguir, com os nomes dos funcionários não mais fisicamente ordenados.

© 2015 - AIEC - Associação Internacional de Educação Continuada

23
114 – Análise das Demonstrações Financeiras | Unidade 01

Bloco físico do Nome Sobrenome Demais campos da


disco tabela...

Daniel Matos Lemos ....

André Matias ...


1
Eduardo Martins ...

Fábio Lemos Maia ...

Mauro Lemos ...

Caio Costa ...


2
Paulo Gomes ...

Caio Ferreira ...

Miriam Leite ...

Bernardo Coelho ...


3
Miriam Felix Coelho ...

André Costa ...

Daniel Costa ...

Felipe César ...


4
Mauro Benvindo ...

André Leite ...

Observe que para um índice secundário, os valores não são organizados sequencialmente.

Quando o bloco de disco apropriado é transferido para um buffer da memória principal, uma pesquisa
pelo registro desejado no bloco pode ser executada. Um índice secundário, em geral, precisa de mais
espaço de armazenamento e tempo de busca maior do que um índice primário, devido a seu maior
número de entradas. Porém, a melhoria no tempo de pesquisa para um registro qualquer é muito maior
para um índice secundário do que para um índice primário, visto que teríamos de fazer uma pesquisa
linear no arquivo de dados se o índice secundário não existisse. Para um índice primário, poderíamos
ainda usar uma pesquisa binária no arquivo principal, mesmo que o índice não existisse.

O próximo exemplo ilustra a melhoria no número de blocos acessados.

© 2015 - AIEC - Associação Internacional de Educação Continuada

24
114 – Análise das Demonstrações Financeiras | Unidade 01

29

Exemplo.

Considere o mesmo arquivo do exemplo anterior, com 30.000 registros de tamanho fixo, de 100 bytes
de tamanho, armazenados em um disco com tamanho de bloco de 1.024 bytes. O arquivo tem 3.000
blocos, conforme já calculamos anteriormente. Suponha que queiramos procurar um registro com um
valor específico para a chave secundária — um campo de chave não ordenado do arquivo que tem 9
bytes de extensão. Sem o índice secundário, para fazer uma pesquisa linear no arquivo, seriam
necessários 3.000/2 = 1.500 acessos de bloco na média (pode ser 1 acesso, se o registro pesquisado for
o primeiro, como pode ser 3.000 acessos, se o registro pesquisado for o último).

Suponha que construíssemos um índice secundário nesse campo de chave não ordenado do arquivo.

Como no exemplo anterior, um ponteiro de bloco tem 6 bytes de extensão, de modo que cada entrada
de índice tem (9 + 6) = 15 bytes (9 do valor pesquisado e 6 do bloco de endereçamento), e o fator de
bloco para o índice é de 1.024/15 = 68 entradas por bloco (cada bloco possui 68 informações de
índices). Em um índice secundário denso como este, o número total de entradas de índice é igual ao
número de registros no arquivo de dados, que é 30.000. O número de blocos necessários para o índice
é, portanto, 30.000/68 = 442 blocos (ou seja, a tabela física ocupa 442 blocos).

Uma pesquisa binária nesse índice secundário precisa de Log2 442 = 9 acessos de bloco. Para procurar
um registro usando o índice, precisamos de um acesso de bloco adicional ao arquivo de dados para um
total de 9 + 1 = 10 acessos de bloco — uma grande melhoria em relação aos 1.500 acessos de bloco
necessários na média para uma pesquisa linear, mas ligeiramente pior que os 7 acessos de bloco
exigidos para o índice primário. Essa diferença surgiu porque o índice primário não era denso e,
portanto, menor, com apenas 45 blocos de extensão.

Observe que um índice secundário oferece uma ordenação lógica nos


registros pelo campo de índice. Se acessarmos os registros na ordem das
entradas no índice secundário, nós os obteremos na ordem do campo de
índice. Os índices primário e de agrupamento assumem que o campo utilizado
para a ordenação física dos registros no arquivo é o mesmo que o campo de
índice.

SGBDs mais antigos liam os dados físicos na mesma ordem que processavam os índices, ou seja, a
cabeça magnética ia para frente e para trás, desperdiçando tempo de acesso (conforme vimos na
unidade passada). Os SGBDs mais modernos, organizam a forma de leitura em memória RAM,
garantindo que a cabeça magnética leia todos os blocos de uma só vez, movendo-se apenas em uma
direção, diminuindo assim o desperdício de tempo causado pela movimentação da cabeça magnética.

© 2015 - AIEC - Associação Internacional de Educação Continuada

25
114 – Análise das Demonstrações Financeiras | Unidade 01

30

RESUMO
Neste módulo, aprendemos que:

a) Índices são estruturas adicionais que oferecem atalhos para acessar os dados solicitados pelos
usuários. Sem um índice o SGBD precisa testar todos os elementos do conjunto, isso é
denominado de pesquisa linear.

b) Um índice geralmente contempla a informação indexada (do mesmo tipo e conteúdo do dado
da tabela) e um ponteiro para o bloco ou o próprio registro (para a coleta das demais
informações do registro).

c) Há várias técnicas de indexação, a mais utilizada é denominada B-tree (árvore binária). Essa
técnica é baseada em separação do conjunto de dados em tamanhos iguais onde o teste é
realizado no ponto médio dessa separação. A fórmula que traduz o resultado de uma pesquisa
binária é Log2 X, onde X corresponde ao número de registros da tabela.

d) O algoritmo de hash é indicado para campos indexados muito extensos. A ideia por trás do
algoritmo de hash é quebrar um arquivo de índices grande em vários arquivos menores, dessa
forma, a pesquisa será feita em um arquivo pequeno.

e) Um índice ordenado de único nível representa o sequenciamento de um ou mais campos de


uma tabela. A pesquisa realizada nesse tipo de índice geralmente é feita por meio do algoritmo
de B-tree. Esse tipo de índice, assim como muitos outros, é criado por meio de um arquivo que
contém de um lado o mesmo conteúdo dos campos da tabela indexados e do outro lado um
ponteiro para o bloco ou o registro.

f) Cada tabela pode ter apenas um índice primário. Este normalmente é atrelado à chave primária
da tabela. Um índice primário define a sequência física de como os registros devem ser
armazenados em disco.

g) Um índice de agrupamento é indicado para tabelas que não possuem uma chave primária e o
campo indexado aceita valores duplicados.

h) Um índice secundário é um índice simples que pode ser aplicado a praticamente qualquer
campo, seja ele obrigatório, opcional, único ou aceitar valores repetidos.

UNIDADE 2 – ESTRUTURAS DE ARQUIVO AUXILIARES

MÓDULO 2 – ÍNDICES (PARTE 2)

© 2015 - AIEC - Associação Internacional de Educação Continuada

26
114 – Análise das Demonstrações Financeiras | Unidade 01

01

1 - IMPLEMENTANDO ÍNDICES
Olá, seja bem-vindo a mais uma etapa do nosso estudo. Nesta etapa iremos estudar como implementar
índices em um SGBD.

Já aprendemos anteriormente que os índices são utilizados para encontrar valores específicos de
colunas de uma maneira rápida. Sem um índice, ocorre o que chamamos de pesquisa linear: o SGBD
precisa iniciar a pesquisa no primeiro registro e percorrer todos os registros da tabela para encontrar os
valores desejados. Quanto maior a tabela, mais custosa é essa operação. Se uma tabela possui um índice
para a coluna pesquisada, o SGBD rapidamente determina a posição para recuperar as informações
desejadas, sem precisar analisar todos os registros da tabela.

Os índices são utilizados para:

 Recuperar registros em cláusulas WHERE.

 Eliminar registros desnecessários.

 Recuperar registros em junções de tabelas que utilizam a cláusula JOIN.

 Encontrar valores mínimos e máximos por meio das funções MIN() e MAX().

 Para classificar resultados utilizando as cláusulas ORDER BY ou GROUP BY.

Veremos agora como implementar índices em um SGBD. Os comandos utilizam a sintaxe SQL, que é
padrão para a maioria dos SGBDs, entretanto, dependendo do SGBD utilizado, algum ajuste pode ser
necessário.

Recuperar registros em cláusulas WHERE.

Com exceção do operador LIKE, índices são utilizados para filtrar e localizar registros em cláusulas
WHERE. Em relacionamento entre tabelas utilizando a cláusula WHERE, os índices também são
usados para garantir o relacionamento.

Eliminar registros desnecessários.

Tanto em relações como em filtragem, os índices auxiliam a eliminar do resultado aqueles registros
desnecessários.

Eliminar registros desnecessários.

© 2015 - AIEC - Associação Internacional de Educação Continuada

27
114 – Análise das Demonstrações Financeiras | Unidade 01

Tanto em relações como em filtragem, os índices auxiliam a eliminar do resultado aqueles registros
desnecessários.

Recuperar registros em junções de tabelas que utilizam a cláusula JOIN.

Assim como relacionamentos feitos por meio de cláusula WHERE, a cláusula JOIN também utiliza
índices.

Encontrar valores mínimos e máximos por meio das funções MIN() e MAX().

Um acesso diretor ao índice normalmente aponta resultados para operadores MIN e MAX,
entretanto, quando são usadas fórmulas internas (como a multiplicação de duas colunas), os índices
são desprezados.

Para classificar resultados utilizando as cláusulas ORDER BY ou GROUP BY.

Toda classificação que é baseada no conteúdo de uma coluna utiliza índices. Entretanto, há
classificações que são, por exemplo, baseadas no resultado de uma operação matemática; esse tipo
de classificação não utiliza índices.

02

1.1 - Como o SGBD processa uma operação SELECT/WHERE quando não há índices

Uma operação com cláusula WHERE, que utiliza comparadores lógicos (>, < e/ou =) normalmente requer
um índice para otimizar a consulta. Quando o índice não existe, os SGBDs mais modernos identificam
essa necessidade e criam índices antes de processar a consulta. Esses índices podem ser criados
temporariamente (geralmente em memória RAM apenas para realizar a consulta), ou quando o serviço
de otimização do SGBD (gerenciador de estatísticas) reconhece que essa necessidade é recorrente, pode
criar o índice fisicamente no disco (de modo definitivo).

Em situações que realmente não há como o SGBD usar ou criar um índice antes do processamento, a
única alternativa de processamento é recorrer a uma pesquisa sequencial processando todos os
registros. Ou seja, para cada registro da condição SELECT, o SGBD processa um a um para ver se as
condições da clausula WHERE são verdadeiras ou falsas. Quando verdadeiras, ele mantém os dados
do registro em memória; quando falsas, ele as despreza.

Exemplo: Vamos supor a operação SELECT * FROM FUNCIONARIOS WHERE Idade > 18 AND Salario >
1.000. Vamos imaginar que a tabela de funcionários possua 10.000 registros:

 Sem índices, o SGBD irá fazer uma operação SELECT para todos os 10.000 registros da tabela
FUNCIONÁRIOS (o que é ineficiente).

© 2015 - AIEC - Associação Internacional de Educação Continuada

28
114 – Análise das Demonstrações Financeiras | Unidade 01

 Para cada um dos registros, o SGBD irá verificar por meio de um teste lógico (operação IF) se
para aquele registro, a condição Idade > 18 AND Salario > 1.000 é verdadeira ou falsa.

 Quando for verdadeira, ele mantém os dados da consulta, quando for falsa, ele despreza os
dados do registro.

 Ao final, ele retornará para o usuário os registros onde a condição foi verdadeira.

Observe que nesse cenário ocorreu a leitura de 10.000 registros (acesso a disco) e também 10.000
testes lógicos.

Veremos no próximo item como o uso de índices permitirá o processamento da mesma consulta com
uma quantidade muito menor de testes lógicos.

03

1.2 - Como o SGBD processa uma operação SELECT/WHERE utilizando um índice

Quando o índice existe, seja ele criado temporariamente ou já preexistente, o SGBD utiliza esses
índices para dividir o conjunto total de registros em subconjuntos menores (usando o algoritmo b-
tree), fazendo assim menos testes lógicos. Ao final, o SGBD irá retornar para o usuário o resultado do
último subconjunto criado.

Exemplo: Vamos supor a mesma operação anterior, SELECT * FROM FUNCIONARIOS WHERE Idade > 18
AND Salario > 1.000, com a tabela de funcionários possuindo 10.000 registros:

 Com índices, o SGBD irá processar as condições da consulta WHERE uma a uma, da mais externa
à mais interna. Dessa forma, primeiramente será processada a operação “Salario > 1.000”.

 O SGBD então analisa o índice de salários, utilizando o algoritmo de b-tree para localizar o ponto
exato onde está o registro que separa aqueles cujo salário é maior que 10.000, daqueles cujo
salário é menor ou igual a 10.000. Já aprendemos que para esse processamento, serão
executados no máximo Log2 10.000, ou seja, 13 operações. Após um máximo de 13 operações, o
SGBD criará em memória um subconjunto de ID’s que satisfazem a condição. Vamos supor que
após esse processamento, o SGBD identifique que 2.000 registros satisfaçam à condição. Então
em memória teremos um subconjunto de 2.000 ID’s da tabela de funcionários (e não mais os
10.000 IDs originais).

 O próximo passo é processar o segundo filtro, “Idade > 18”; para tal, o SGBD utilizará agora o
índice de Idade. A partir do conjunto de 2.000 IDs que ele tem em memória, resultado do filtro
anterior, o SGBD irá processar o algoritmo b-tree no índice de Idade para localizar qual é o

© 2015 - AIEC - Associação Internacional de Educação Continuada

29
114 – Análise das Demonstrações Financeiras | Unidade 01

ponto de corte para a operação desejada. Novamente, aplicando a fórmula Log2 2.000, há um
máximo de 10 operações para que o SGBD identifique os registros desejados. A partir desse
ponto, o SGBD cria outro subconjunto de IDs apenas com os resultados verdadeiros. Vamos
supor que ao aplicar esse segundo filtro, o SGBD tenha reduzido o subconjunto de IDs para
apenas 800 registros.

 Agora que o SGBD já sabe quais registros satisfazem às duas condições de filtros aplicadas, ele
irá fazer uma consulta ao disco para identificar todos os dados (SELECT * FROM
FUNCIONARIOS...) dos 800 funcionários que satisfazem os critérios da pesquisa (Salario > 1.000
e Idade > 18).

Observe que o número máximo de testes lógicos executados foi de apenas 23 operações, contra
10.000 operações do modelo anterior (sem uso de índices), e que o acesso a disco leu apenas 800
registros, contra 10.000 do modo anterior. Dessa forma, fica claro que o uso de índices é
extremamente benéfico para aumentar a performance das consultas SQL.

04

1.3 - Como o SGBD processa uma operação que contenha a expressão LIKE

Operações SQL que utilizam a expressão LIKE não utilizam índices; essas operações fazem pesquisa
linear em todos os dados do conjunto de dados. Se uma instrução SQL possuir um operador LIKE e
algum outro operador lógico (como os citados anteriormente), primeiramente os operadores lógicos
serão processados (utilizando índices) e diminuindo o conjunto de dados, e, posteriormente o
operador LIKE será executado apenas nesse subconjunto, por meio de uma consulta linear.

Exemplo: Vamos ver como o SGBD processa a operação SELECT * FROM FUNCIONARIOS WHERE Nome
LIKE “%Marcelo%” AND Idade > 18 AND Salario > 1000. Vamos supor ainda que a tabela de funcionários
possua 10.000 registros:

 Primeiro o SGBD analisa a instrução à procura de operações de filtragem de registros e identifica


que há três operações.

 Na sequência ele verifica quais índices existem para as consultas apresentadas. Vamos supor
que ele tenha identificado que há um índice para Nome, outro para Idade e outro para Salário.

 Ao observar que a operação sobre o campo Nome é uma instrução LIKE, o SGBD despreza esse
índice, ficando agora com dois índices.

 O SGBD processa inicialmente o filtro mais externo da instrução SQL, ou seja, Salario > 1000,
realizando a operação sobre o índice de Salário. Vamos supor que dos 10.000 registros iniciais,

© 2015 - AIEC - Associação Internacional de Educação Continuada

30
114 – Análise das Demonstrações Financeiras | Unidade 01

apenas 2.000 satisfazem essa condição; o SGBD então cria em memória um subconjunto dos ID’s
de chave primária desses 2.000 registros que satisfazem a condição (já vimos que essa operação
é feita por meio do algoritmo b-tree).

 Na sequência, o SGBD processa o filtro seguinte, ou seja, Idade > 18, realizando essa operação
apenas no subconjunto de ID’s de chave primária criado no passo anterior. Vamos supor que ao
aplicar esse filtro no subconjunto criado ele tenha identificado que apenas 800 dos 2.000
registros atendem ao critério (novamente usando o algoritmo b-tree). Então ele cria um outro
subconjunto, menor, com apenas 800 ID’s de chave primária.

 Agora só resta ao SGBD processar a operação LIKE. Como essa operação não é baseada em
índice, ele utilizará o subconjunto criado de 800 ID’s para processar a operação LIKE desejada.
Vamos supor que ao processar essa operação, o SGBD identifique que 30 registros atendem à
essa condição (foram realizados 800 testes lógicos para essa operação).

 Agora, o SGBD fará a leitura de todos os campos (SELECT * FROM FUNCIONARIOS...) desses 30
registros identificados, retornando o resultado para o usuário.

Veja no exemplo acima que a pesquisa linear do operador LIKE não foi
processada nos 10.000 registros do conjunto, mas somente nos 800 registros
que atenderam às duas outras condições impostas na cláusula WHERE.
Entretanto, a consulta consumiu 23 testes lógicos para os dois filtros iniciais e
mais 800 para o filtro LIKE, totalizando 823 testes lógicos. Perceba como as
operações LIKE podem ser extremamente onerosas para o banco de dados!

05

2 - CRIANDO, ALTERANDO E EXCLUINDO ÍNDICES


Nesta seção, iremos aprender os comandos SQL necessários para criar, alterar e excluir índices.

2.1 - Índice de chave primária

Já estudamos anteriormente que a chave primária é o campo que identifica unicamente qualquer um
dos registros de uma tabela. Por definição, uma chave primária não pode receber o valor nulo nem
aceitar dados duplicados. Na grande maioria dos modelos de dados, a chave primária é um número
sequencial, sendo que a cada inserção, um novo número é gerado a partir do último valor criado,
acrescido de 1. Por outro lado, o valor de chave pode ser uma string, uma data/hora, ou qualquer outro
tipo de dado, o que é bem menos usual.

O índice de chave primária é criado com o parâmetro PRIMARY KEY, que define um índice primário e
a ordenação física dos elementos da tabela. Só pode haver uma chave primária em uma tabela, mas
ela pode ser relacionada a um só campo ou a vários campos (chave composta).

© 2015 - AIEC - Associação Internacional de Educação Continuada

31
114 – Análise das Demonstrações Financeiras | Unidade 01

Quando relacionado a um só campo, geralmente trata-se uma entidade forte. Esse campo é o
identificador da tabela e normalmente possui as expressões “ID”, “COD”, “CODIGO” como parte do
nome do campo.

Exemplo: Em uma tabela de Funcionários, o campo ID_Funcionario seria uma boa escolha de nome para
o campo chave primária dessa tabela. Veja a seguir como seria a criação de uma nova tabela com a
definição de uma chave primária (destacamos em amarelo o identificador de chave primária):

CREATE TABLE FUNCIONARIOS (

ID_Funcionario INT PRIMARY KEY,

Nome VARCHAR (255))

06

Durante a criação da tabela, a definição da chave primária pode ser feita em dois locais diferentes da
expressão SQL:

 ou após o nome do campo, como vimos no exemplo anterior,

 ou como uma linha a mais depois da lista de campos da tabela.

Veja como seria a mesma definição de tabela do exemplo anterior, mas com a definição da chave
primária após a definição dos campos:

CREATE TABLE FUNCIONARIOS (

ID_Funcionario INT,

Nome VARCHAR (255),

PRIMARY KEY (ID_Funcionario))

As tabelas normalmente possuem apenas uma chave primária, entretanto, as tabelas associativas
geralmente recebem as chaves primárias de outras tabelas para identificá-las. Dessa forma, a chave
primária de uma tabela associativa pode ser formada pela união das chaves primárias de duas ou mais
tabelas.

Exemplo: suponha que em um banco de dados um funcionário pode ter vários endereços e um
endereço possa pertencer a vários funcionários. Para criar essa relação, precisaremos de uma tabela
associativa que une funcionários a endereços. Essa tabela poderia se chamar, por exemplo, de
FUNCIONARIOS_ENDERECOS e possuir ID_Funcionario e ID_Endereco, juntas, como chave primária. Para

© 2015 - AIEC - Associação Internacional de Educação Continuada

32
114 – Análise das Demonstrações Financeiras | Unidade 01

chaves primárias que incluem mais de um campo, somente é possível usar a segunda forma de
especificação de cláusula SQL (com a identificação após a lista de campos). Veja a seguir como seria a
definição de uma chave primária baseada em dois campos:

CREATE TABLE FUNCIONARIOS_ENDERECOS (

ID_Funcionario INT,

ID_Endereco INT,

Logradouro VARCHAR (255),

...demais campos...

PRIMARY KEY (ID_Funcionario, ID_Endereco))

07

2.1.1 - Índice UNIQUE

Um índice UNIQUE tem um comportamento diferente, seu objetivo principal não é a pesquisa ágil de
dados, mas sim a definição de uma restrição que determina que todos os registros do índice devem
ser únicos (sem valores repetidos).

Dessa forma, um erro é gerado caso uma instrução INSERT ou UPDATE gere um registro com um valor
idêntico a outro registro. Um campo com uma restrição UNIQUE pode ser configurado para aceitar ou
não valores nulos. Um índice UNIQUE precisa de um nome para identificá-lo. Esse nome é definido no
momento da criação do índice. É comum usar sufixos ou prefixos que lembrem a expressão “índice”,
como i_, index_, ind_, ix_ no nome dos índices.

Esse tipo de restrição é criado, por exemplo, em chaves secundárias, muito utilizadas para identificações
por códigos alternativos como e-mail, CPF, CNPJ, matrícula e outros. O exemplo a seguir apresenta uma
instrução de criação de uma tabela com uma restrição de unicidade aplicada ao campo de CPF (índice de
nome ix_CPF:

CREATE TABLE FUNCIONARIOS (

ID_Funcionario INT PRIMARY KEY,

Nome VARCHAR (255)

CPF VARCHAR (11) UNIQUE KEY ix_CPF)

© 2015 - AIEC - Associação Internacional de Educação Continuada

33
114 – Análise das Demonstrações Financeiras | Unidade 01

08

Da mesma forma que podemos ter uma chave primária múltipla (formada por mais de um atributo),
também podemos ter um índice de unicidade múltiplo. Por exemplo, o cadastro de números de
telefone, que possui campos para código do país, prefixo DDD da área e número do telefone, poderia ter
um índice de unicidade que levasse em conta esses três campos. Dessa forma, não poderiam ser
cadastrados números repetidos.

A definição de um índice de unicidade múltiplo é feita logo após a linha de criação da chave primária, e
obedece ao padrão UNIQUE KEY nome_do_índice (campo1, campo2, ..., campo n).

Veja a seguir como seria a criação de uma tabela de telefone com a restrição de unicidade citada:

CREATE TABLE TELEFONES (

ID_Telefone INT NOT NULL,

Pais INT NOT NULL,

Area INT NOT NULL,

Numero DECIMAL(10,0) NOT NULL,

PRIMARY KEY (ID_Telefone),

UNIQUE KEY ix_telefone (Pais, Area, Numero))

09

2.2 - Índices secundários

Os índices secundários, como já vimos anteriormente, ordenam valores que não são chave primária.
Um índice secundário pode ou não possuir valores repetidos, essa definição é feita com o parâmetro
UNIQUE quando não se deseja valores duplicados. Um campo com um índice secundário também
pode ou não possuir valores nulos (ou seja, definindo se o campo é obrigatório ou não, por meio da
cláusula NULL ou NOT NULL na criação do campo).

Um índice secundário pode ser criado junto com a tabela (operação CREATE TABLE), mas também é
muito comum de serem criados em um ambiente já existente, para otimização do banco de dados.
Neste segundo caso, os índices secundários podem ser criados com a operação CREATE INDEX.

O exemplo a seguir apresenta a criação de um índice de nome ix_nome, no campo Nome da tabela de
FUNCIONÁRIO:

© 2015 - AIEC - Associação Internacional de Educação Continuada

34
114 – Análise das Demonstrações Financeiras | Unidade 01

CREATE INDEX ix_nome

ON FUNCIONÁRIO (Nome)

Para sinalizar que o índice é do tipo único, basta acrescentar a expressão UNIQUE após a expressão
CREATE, conforme seguinte exemplo:

CREATE UNIQUE INDEX ix_nome

ON FUNCIONÁRIO (Nome)

10

2.3 - Índices Textuais

Campos do tipo TEXT, CHAR e VARCHAR podem ter um índice especificar denominado “índice
textual”. Diferentemente de um índice tradicional que todos os dados de um registro são indexados,
esse tipo de índice classifica todas as palavras, individualmente, criando uma estrutura que permite
pesquisar palavra por palavra.

Com isso, campos com muitas informações podem se beneficiar desse tipo de índice em pesquisas.

A utilização de um índice FULL TEXT pode requerer uma configuração específica do SGBD ou mesmo a
instalação de um plug-in à parte para que tal funcionalidade seja disponibilizada.

O uso de índices FULL TEXT consomem muito espaço de memória, mas permitem um recurso
interessantíssimo: indexar documentos, como documentos Ms Word ou PDF. Com isso, é possível fazer
pesquisas por palavras armazenadas em arquivos textuais, onde o sistema de informação pode, por
exemplo, complementar a funcionalidade apresentando o arquivo identificado ou trechos do
documento que contenham a informação desejada.

A forma pela qual um índice FULL TEXT é criado e utilizado muda muito de
SGBD para SGBD, dessa forma, não há um padrão que possamos deixar aqui
como referência. Portanto, caso você queira saber mais sobre índices FULL
TEXT, consulte o manual do seu SGBD.

11

2.4 - Mostrando os índices existentes de uma tabela

© 2015 - AIEC - Associação Internacional de Educação Continuada

35
114 – Análise das Demonstrações Financeiras | Unidade 01

Já falamos que índices secundários e únicos precisam de um nome. Falamos também que para modificar
e/ou excluir esses índices precisamos saber o nome do índice. Então, como saber o nome de um índice?

Há um comando SQL que apresenta uma lista de todos os índices criados para uma tabela específica.
Esse comando é o SHOW INDEX e tem o seguinte layout:

SHOW INDEX FROM nome_da_tabela.

A tela a seguir apresenta um exemplo de resposta para o comando SHOW INDEX em um SGBD My SQL:

Exemplo do resultado do comando SHOW INDEX

Observe informações importantes como a indicação se o índice é único ou


não, o nome do índice, a coluna à qual o índice se refere, se aceita valores
nulos e o tipo de algoritmo usado.

12

2.5 - Excluindo índices

Um índice pode ser excluído de um banco de dados utilizando o comando DROP INDEX. Para executar
esse comando, a sintaxe é DROP INDEX nome ou tipo do índice ON nome da tabela.

É essencial saber o nome do índice para sua exclusão, já que não é possível excluir um índice usando
apenas a coluna como informação.

© 2015 - AIEC - Associação Internacional de Educação Continuada

36
114 – Análise das Demonstrações Financeiras | Unidade 01

Por exemplo, para se excluir o índice de chave primária da tabela FUNCIONÁRIO, utiliza-se o operador
PRIMARY, conforme o seguinte exemplo:

DROP INDEX PRIMARY ON FUNCIONARIO.

Para excluir o índice ix_nome da tabela de FUNCIONÁRIO, utilizaríamos o seguinte comando:

DROP INDEX ix_nome ON FUNCIONARIO

13

2.6 - Comando Alter Table

O comando ALTER TABLE permite uma série de funcionalidades que alteram a estrutura de uma
tabela. Entre as modificações possíveis de serem implementadas com este comando estão a criação e
a exclusão de índices.

Para a criação de índices, a sintaxe padrão é:

 ALTER TABLE Nome_da_tabela ADD PRIMARY KEY (lista_de_campos);

 ALTER TABLE Nome_da_tabela ADD UNIQUE nome_do_índice (lista_de_campos);

 ALTER TABLE Nome_da_tabela ADD INDEX nome_do_índice (lista_de_campos);

 ALTER TABLE Nome_da_tabela ADD FULLTEXT nome_do_índice (lista_de_campos).

A funcionalidade ALTER TABLE também permite a exclusão de índices. Dois exemplos de exclusão de
índices, utilizando o comando ALTER TABLE teriam a seguinte forma:

ALTER TABLE FUNCIONÁRIO DROP PRIMARY KEY

ALTER TABLE FUNCIONÁRIO DROP INDEX ix_nome

ALTER TABLE Nome_da_tabela ADD PRIMARY KEY (lista_de_campos)

Para criar uma chave primária.

© 2015 - AIEC - Associação Internacional de Educação Continuada

37
114 – Análise das Demonstrações Financeiras | Unidade 01

ALTER TABLE Nome_da_tabela ADD UNIQUE nome_do_índice (lista_de_campos)

Para criar um índice de exclusividade.

ALTER TABLE Nome_da_tabela ADD INDEX nome_do_índice (lista_de_campos)

Para criar um índice secundário.

ALTER TABLE Nome_da_tabela ADD FULLTEXT nome_do_índice (lista_de_campos)

Para criar um índice do tipo texto indexado.

14

RESUMO
Neste módulo, aprendemos que:

a) Uma pesquisa linear é operação de consulta não otimizada onde o SGBD processa
sequencialmente todos os dados a fim de identificar os registros que satisfazem determinada
condição. Esse tipo de operação não utiliza índices, seja pela inexistência deles ou pela
impossibilidade de criação destes.

b) Quando não há índices, mas os mesmos são necessários, alguns SGBDs podem criar índices
temporários (em memória RAM) ou definitivos (em disco) a fim de otimizar as operações de
dados.

c) Quando há índices, o SGBD seleciona os dados a serem lidos usando técnicas como a b-tree.

d) Os índices normalmente são criados no momento da definição do modelo de dados, entretanto,


índices secundários podem ser criados ao longo do uso do banco de dados, na busca por
maiores performances das operações.

e) Índices de chave primária podem ser criados em um campo apenas ou em vários (chave
composta).

f) Um índice UNIQUE tem como principal objetivo evitar o cadastro de dados duplicados em uma
tabela.

g) O comando CREATE INDEX cria índices secundários. Para especificar que o índice é do tipo único,
acrescenta-se o operador UNIQUE.

h) Para excluir um índice, usa-se o comando DROP INDEX. Alternativamente, pode-se usar o
comando ALTER TABLE para excluir índices.

© 2015 - AIEC - Associação Internacional de Educação Continuada

38
114 – Análise das Demonstrações Financeiras | Unidade 01

i) O comando SHOW INDEX apresenta os índices existentes para uma determinada tabela. Esse
comando inclui informações complementares importantes como unicidade, campo indexado,
nulidade e algoritmo utilizado.

UNIDADE 2 – ESTRUTURAS DE ARQUIVO AUXILIARES

MÓDULO 3 – TRANSAÇÕES
01

1 - PROCESSAMENTO DE TRANSAÇÕES
Olá, seja bem-vindo a mais um módulo de estudos da disciplina Banco de dados II. Nesta etapa iremos
estudar o contexto transacional de um banco de dados.

Os bancos de dados transacionais são aqueles que suportam o conceito de transação.

Por definição base, uma transação refere-se a uma operação lógica sobre um determinado dado. Essa
operação pode ser uma consulta, uma alteração, uma inserção ou uma exclusão de dados.

Outro conceito fundamental sobre a gestão transacional refere-se ao ato controlado de duas ou mais
operações intrinsecamente coordenadas e integradas que afetem o repositório dos dados. Exemplo:
uma transferência de fundos de uma conta corrente “A” para uma conta corrente “B” só pode ser
considerada válida se tanto a operação de débito da conta “A” quanto a operação de crédito da conta
“B” forem válidas. Dessa forma, o SGBD (e consequentemente o sistema de informação) deve prover
mecanismos que controlem e gerenciem todo e qualquer tipo de alteração de dado.

Caso seja necessário desfazer uma operação, o SGBD deve possuir informações sobre os dados originais,
de forma a ser possível voltar para o conteúdo anterior da informação. Exemplo: se a operação de
crédito na conta “B” falhar, o SGBD deve ser capaz de desfazer a operação de débito da conta “A”,
retornando o saldo para o valor anterior.

Além do controle desse tipo de operação, um banco de dados transacional possui as seguintes
características:

© 2015 - AIEC - Associação Internacional de Educação Continuada

39
114 – Análise das Demonstrações Financeiras | Unidade 01

 Capacidade para gerenciar o pedido de centenas (ou milhares) de usuários ao mesmo tempo,
serializando as operações.

 Capacidade de controlar operações que possam gerar conflitos, como duas operações
tentando alterar o mesmo registro ao mesmo tempo.

 Capacidade de desfazer operações e voltar o banco de dados a uma situação anterior definida
em um determinado momento (data/hora).

Neste capítulo, discutiremos os conceitos de execução concorrente de transações e recuperação de


transações com falhas.

02

2 - SISTEMAS MONOUSUÁRIO VERSUS SISTEMAS MULTIUSUÁRIO


Um critério para classificar um sistema de banco de dados é de acordo com o número de usuários que
podem usar o sistema simultaneamente. Um SGBD é monousuário se somente um usuário de cada vez
pode utilizar o sistema, e é multiusuário se muitos usuários puderem fazê-lo — e, portanto, acessar o
banco de dados — simultaneamente.

Os SGBDS monousuário são principalmente restritos a sistemas de computador pessoal; a maioria


dos outros SGBDs é multiusuário. Por exemplo, um sistema de reservas aéreas é acessado por
centenas de agentes de viagens e funcionários de reserva de maneira simultânea. Os sistemas de
banco de dados usados em bancos, agências de seguros, mercado de ações, supermercados e muitas
outras aplicações são de multiusuários. Nesses sistemas, centenas ou milhares de usuários
normalmente estão operando no banco de dados ao submeter transações ao sistema ao mesmo
tempo.

Multiusuários podem acessar os bancos de dados e usar sistemas de computação simultaneamente


devido ao conceito da multiprogramação, que permite que o sistema operacional do computador
execute vários programas (ou processos) ao mesmo tempo.

Uma única unidade central de processamento (CPU) pode executar apenas, e no máximo, um processo
de cada vez. Porém, sistemas operacionais de multiprogramação executam alguns comandos de um
processo, depois suspendem esse processo e executam alguns comandos do processo seguinte, e assim
por diante. Um processo é retomado no ponto em que foi suspenso sempre que chega sua vez de usar a
CPU novamente. Assim, a execução simultânea dos processos é, na realidade, intercalada, também
denominada de serializada. Veja um exemplo.

© 2015 - AIEC - Associação Internacional de Educação Continuada

40
114 – Análise das Demonstrações Financeiras | Unidade 01

A intercalação mantém a CPU ocupada quando um processo exige uma operação de entrada ou saída,
como a leitura de um bloco do disco. A CPU troca e realiza outro processo, em vez de permanecer ociosa
durante o tempo de leitura de dados. A intercalação também impede que um processo longo atrase os
demais processos. Veja como.

Para o restante deste módulo, assumiremos esse modelo.

Veja um exemplo

Um exemplo disso é quando você clica no ícone de dois programas para serem carregados no
computador. A CPU não carrega um programa completamente para depois carregar o segundo, ela
fragmenta os pedidos e faz com que ambas vão sendo carregadas ao mesmo tempo.

Veja como

Se o sistema de computação tiver múltiplos processadores de hardware (CPUs), o processamento


paralelo de vários processos é possível. A maior parte da teoria referente ao controle de concorrência
nos bancos de dados é desenvolvida em relação à concorrência intercalada.

03

2.1 - Transações, itens de banco de dados, operações de leitura e gravação e buffers do SGBD

Uma transação é um programa em execução que forma uma unidade lógica de processamento de
banco de dados.

Ela inclui uma ou mais operações de acesso ao banco de dados — estas podem incluir operações de
inserção, exclusão, modificação ou recuperação.

As operações de banco de dados que formam uma transação podem ser embutidas em um programa de
aplicação ou podem ser especificadas interativamente por meio de uma linguagem de consulta de alto
nível, como a SQL.

As operações estruturais de banco de dados (comando DDL, como a criação


de tabelas, índices, usuários) não são regidas por transações; apenas as
operações de manipulação de dados (comandos DML) são possíveis de serem
controladas por transações.

Um modo de especificar os limites de uma transação é usando as instruções explícitas begin transaction
(ou start transacion em alguns SGBDs) e commit transaction (ou end transaction em alguns SGBDs);

© 2015 - AIEC - Associação Internacional de Educação Continuada

41
114 – Análise das Demonstrações Financeiras | Unidade 01

nesse caso, todas as operações de acesso ao banco de dados entre os dois comandos são consideradas
uma transação.

Um único programa de aplicação pode conter mais de uma transação se tiver vários limites de
transação. Se as operações de banco de dados em uma transação não atualizarem o banco de dados,
mas apenas recuperarem dados, a transação é chamada de transação de leitura; caso contrário, ela é
conhecida como transação de leitura-gravação. Veja a estrutura de uma transação:

BEGIN TRANSACTION;
Comando SQL;
Comando SQL;
Comando SQL;
(...);
COMMIT;

04

2.2 - Gerenciamento do buffer de gravação

Generalizando as instruções SQL, as operações básicas de acesso ao banco de dados que uma transação
pode incluir são as seguintes:

 Read_item(X): Lê um item do banco de dados chamado X para uma variável do programa.


Para simplificar nossa notação, consideramos que a variável de programa também é chamada
X.

 Write_item(X): Grava o valor da variável de programa X no item de banco de dados


chamado X.

Conforme discutimos em momentos anteriores, a unidade básica de transferência de dados do disco


para a memória principal é um bloco.

A execução de um comando read_item(X) inclui as seguintes etapas:

2- Copie esse bloco de


disco para um buffer na
3- Copie o item X do
1- Ache o endereço do memória principal (se
buffer para a variável
bloco de disco que esse bloco de disco
de programa chamada
contém o item X. ainda não estiver em
X.
algum buffer da
memória principal).

© 2015 - AIEC - Associação Internacional de Educação Continuada

42
114 – Análise das Demonstrações Financeiras | Unidade 01

05

A execução de um comando write_item(X) inclui as seguintes etapas:

2- Copie esse
bloco de disco 4- Armazene o
1- Ache o para um buffer 3- Copie o item X bloco atualizado
na memória da variável de do buffer de
endereço do
principal (se esse programa volta no disco
bloco de disco bloco de disco chamada X para (imediatamente
que contém o ainda não estiver 0 local correto ou em algum
item X. em algum buffer no buffer. momento
da memória posterior).
principal).

É a etapa 4 que de fato atualiza o banco de dados no disco. Em alguns casos, o buffer não é
imediatamente armazenado no disco, caso mudanças adicionais tenham de ser feitas no buffer.

Em geral, a decisão sobre quando armazenar um bloco de disco modificado, cujo conteúdo está em um
buffer da memória principal, é tratada pelo gerenciador de recuperação do SGBD em cooperação com o
sistema operacional subjacente.

06

O SGBD manterá na cache do banco de dados (memória RAM) uma série de buffers de dados. Cada
buffer costuma manter o conteúdo de um bloco de disco do banco de dados, que contém alguns dos
itens de banco de dados que estão sendo processados. Quando esses buffers estão todos ocupados, e
blocos de disco de banco de dados adicionais devem ser copiados para a memória, alguma política de
substituição de buffer é utilizada para escolher quais buffers atuais devem ser substituídos.

Se um buffer escolhido tiver sido modificado, ele precisa ser gravado de volta no disco antes de ser
reutilizado. Entretanto, a execução de um comando do tipo COMMIT força a gravação física dos dados
no disco.

Uma transação inclui operações read_item() e write_item() para acessar e atualizar o banco de dados.
O conjunto de leitura de uma transação é o conjunto de todos os itens que a transação lê, e o
conjunto de gravação é o conjunto de todos os itens que a transação grava.

Os mecanismos de controle de concorrência e recuperação tratam


principalmente dos comandos de banco de dados em uma transação. As
transações submetidas pelos diversos usuários podem ser executadas
simultaneamente, acessar e atualizar os mesmos itens de banco de dados. Se
essa execução simultânea for descontrolada, ela pode ocasionar problemas,
como um banco de dados inconsistente.

© 2015 - AIEC - Associação Internacional de Educação Continuada

43
114 – Análise das Demonstrações Financeiras | Unidade 01

Na próxima seção, apresentamos de maneira informal alguns dos problemas que podem ocorrer.

07

2.3 - Por que o controle de concorrência é necessário?

Vários problemas podem acontecer quando transações simultâneas são executadas de uma maneira
descontrolada. Ilustramos alguns desses problemas ao nos referirmos a um sistema bancário de
controle de conta corrente.

O exemplo a seguir apresenta duas operações bancárias acontecendo simultaneamente, uma, de um


depósito bancário de R$100,00 e outra, de um pagamento de R$ 80,00.

Tempo Operação UM (depósito) Operação DOIS (pagamento)

1 Ler saldo atual. Ler saldo atual.

2 Sistema retorna R$ 1.000,00. Sistema retorna R$ 1.000,00.

Processando o depósito: calcula saldo


Processando o pagamento: calcula saldo atual =
3 atual = saldo atual + R$ 100,00; saldo
saldo atual – R$ 80,00; saldo atual – R$ 920,00.
atual = R$ 1.100,00.

Armazena R$ 1.100 como saldo atual


4 Armazena R$ 920,00 como saldo atual do banco.
no banco.

Erro, pois o saldo atual real deveria ser R$


5
1.020,00.

Perceba que a segunda operação invalida a primeira e vice-versa, pois o saldo atual da segunda
operação não pode mais ser considerado como o valor atual.

Esse problema ocorre quando duas transações que acessam os mesmos itens do banco de dados têm
suas operações intercaladas de modo que isso torna o valor de alguns itens do banco de dados
incorreto. Esse tipo de problema é denominado problema da atualização perdida.

08

© 2015 - AIEC - Associação Internacional de Educação Continuada

44
114 – Análise das Demonstrações Financeiras | Unidade 01

Outro tipo de problema é a atualização temporária (ou leitura suja). Esse problema ocorre quando
uma transação atualiza um item do banco de dados e depois a transação falha por algum motivo.
Nesse meio tempo, o item atualizado é acessado (lido) por outra transação, antes de ser alterado de
volta para seu valor original.

Vejamos um exemplo:

Tempo Operação UM Operação DOIS

1 Iniciar transação.

2 Ler valor de X no banco.

3 Sistema retorna 10.

4 Calcular X + 5 = 15. Iniciar transação.

5 Gravar 15 no banco. Ler valor de X no banco.

6 Ler valor Y no banco. Sistema retorna 15.

7 Erro de leitura. Calcular X + 5 = 20.

8 Desfazer transação. X volta a ser 10. Gravar 20 no banco.

9 Erro, pois o valor original de X não é mais 15,


mas sim, 10.

O exemplo acima ilustra a operação UM sobre o item X que então falha antes de terminar, de modo que
o sistema deve mudar o valor de X de volta para seu valor original. Contudo, antes que ele possa fazer
isso, a operação DOIS lê o valor temporário de X, que não será gravado permanentemente no banco de
dados devido à falha da operação UM.

O valor do item X que foi lido pela operação DOIS é chamado de dado sujo, pois foi criado por uma
transação que não foi concluída nem confirmada; portanto, a transação DOIS deve ser cancelada. Esse
problema também é conhecido como problema de leitura suja.

09

Outra situação é denominada de problema do resumo incorreto. Se uma transação está calculando
uma função de resumo de agregação em uma série de itens de banco de dados, enquanto outras

© 2015 - AIEC - Associação Internacional de Educação Continuada

45
114 – Análise das Demonstrações Financeiras | Unidade 01

transações estão atualizando alguns desses itens, a função de agregação pode calcular alguns valores
antes que eles sejam atualizados e outros, depois que eles forem atualizados.

Por exemplo, suponha que uma transação T1 esteja calculando o volume de operações financeiras de
uma determinada conta corrente; enquanto isso, outra transação T2 está criando um crédito nessa
mesma conta. Se a intercalação de operações acontecer, o resultado de T1 estará defasado da operação
T2.

Por fim, há o problema da leitura não repetitiva. Esse problema pode ocorrer em uma transação que
precisa ler o mesmo item duas vezes, e antes de ler a segunda vez ocorre uma mudança no valor do
dado.

10

2.4 - Por que a recuperação é necessária?

Sempre que uma transação é submetida a um SGBD para execução, o sistema é responsável por garantir
que todas as operações na transação sejam concluídas com sucesso e seu efeito seja registrado
permanentemente no banco de dados, ou que a transação não tenha qualquer efeito no banco de
dados ou quaisquer outras transações.

No primeiro caso, a transação é considerada confirmada (committed), ao passo que, no segundo caso, a
transação é abortada (rollback).

O SGBD não deve permitir que algumas operações de uma transação sejam aplicadas ao banco de dados
enquanto outras operações da mesma transação não são, pois, a transação inteira é uma unidade lógica
de processamento de banco de dados.

Se a transação falhar depois de executar algumas de suas operações, mas


antes de executar todas elas, as operações já executadas precisam ser
desfeitas.

11

2.5 - Tipos de falhas

As falhas geralmente são classificadas como:

 falhas de transação,

 falhas de sistema e

 falhas de mídia.

© 2015 - AIEC - Associação Internacional de Educação Continuada

46
114 – Análise das Demonstrações Financeiras | Unidade 01

Existem vários motivos possíveis para uma transação falhar no meio da execução:

1. Uma falha do computador (falha do sistema).

2. Um erro de transação ou do sistema.

3. Erros locais ou condições de exceção detectadas pela transação.

4. Imposição de controle de concorrência.

5. Falha de disco.

6. Problemas físicos e catástrofes.

Sempre que ocorre uma falha, o sistema precisa manter informações suficientes para recuperar-se
rapidamente da falha.

O conceito de transação é fundamental para muitas técnicas de controle de concorrência e recuperação


de falhas. Entretanto, nem todas as situações possíveis podem ser previstas apenas pelo controle
transacional. Um incêndio, por exemplo, é um evento externo que não pode ser gerenciado por um
controle transacional.

Dependendo da importância do sistema, técnicas como computação distribuída, replicação de sites, e


outros, podem ser necessárias para manter o sistema funcional.

Uma falha do computador (falha do sistema).

Um erro de hardware, software ou rede no sistema de computação durante a execução da transação.


Falhas do hardware normalmente são falhas de mídia — por exemplo, uma falha na memória
principal ou do processador.

Um erro de transação ou do sistema.

Alguma operação na transação pode fazer que esta falhe, como um estouro de inteiro ou divisão por
zero. A falha da transação também pode ocorrer devido a valores de parâmetro errôneos ou a um
erro lógico de programação. Além disso, o usuário pode interromper a transação durante sua
execução.

Erros locais ou condições de exceção detectadas pela transação.

Durante a execução da transação, podem ocorrer certas condições que necessitam de cancelamento
da transação. Por exemplo, os dados da transação podem não ser encontrados. Uma condição de
exceção, como um saldo de conta insuficiente em um banco de dados bancário, pode fazer que uma

© 2015 - AIEC - Associação Internacional de Educação Continuada

47
114 – Análise das Demonstrações Financeiras | Unidade 01

transação, como um saque, seja cancelada. Essa exceção poderia ser programada na própria
transação, e nesse caso não seria considerada uma falha da transação.

Imposição de controle de concorrência.

O método de controle de concorrência (veremos mais a frente) pode decidir abortar uma transação
porque ela viola a serialização, ou pode abortar uma ou mais transações para resolver um estado de
deadlock entre várias transações. As transações abortadas devido a violações de serialização ou
deadlock em geral são reiniciadas automaticamente em outro momento.

Falha de disco.

Alguns blocos de disco podem perder seus dados devido a um defeito de leitura, gravação ou por
causa de uma falha da cabeça de leitura/gravação. Isso pode acontecer durante uma operação de
leitura ou gravação da transação.

Problemas físicos e catástrofes.

Isso se refere a uma lista sem fim de problemas que incluem falha de energia ou de ar-condicionado,
incêndio, roubo, sabotagem, regravação de discos ou fitas por engano e montagem da fita errada
pelo operador.

12

2.6 - Conceito de transação e sistema

Nesta etapa, discutiremos os conceitos de estados de transação e log do sistema.

2.6.1 - Estados de transação e operações adicionais

Já aprendemos que uma transação é uma unidade atômica de trabalho, que deve ser concluída
totalmente ou não ser feita de forma alguma.

Para fins de recuperação (desfazendo os passos já realizados), o sistema precisa registrar os dados
originais e quando cada transação começa, termina e é confirmada (ou abortada). Portanto, o
gerenciador de recuperação do SGBD precisa acompanhar as seguintes operações:

© 2015 - AIEC - Associação Internacional de Educação Continuada

48
114 – Análise das Demonstrações Financeiras | Unidade 01

 BEGIN TRANSACTION

Esta operação marca o início da execução da transação.

 Operações READ ou WRITE (SELECT, INSERT, UPDATE, DELETE, CREATE etc.)

Essas operações especificam as operações de leitura ou gravação dentro de um determinado banco


de dados.

 COMMIT (ou END TRANSACTION)

Esta operação determina o fim da transação e confirma positivamente as operações realizadas


(confirmando a persistência dos dados).

 ROLL BACK (ou ABORT)

Esta operação sinaliza que uma transação encerrou sem sucesso e, portanto, quaisquer mudanças
ocorridas no banco de dados devem ser desfeitas.

13

O fluxo de uma transação pode ser observado no diagrama a seguir.

Uma transação entra em um estado


ativo imediatamente após a execução Início
do comando de BEGIN TRANSACTION,
onde todas as operações de leitura a Begin transaction

gravação serão controladas.


Operações Read e
Write

Falha
Nesse ponto, alguns protocolos de Todas operações realizadas com sucesso
recuperação precisam garantir que uma
falha no sistema não resultará em uma Parcialmente
Roll Back
incapacidade de registrar as mudanças confirmado
da transação permanentemente.
Commit

Confirmado Abortado
Quando essa verificação é bem-
sucedida, a transação pode ser

© 2015 - AIEC - Associação Internacional de Educação Continuada

49
114 – Análise das Demonstrações Financeiras | Unidade 01

confirmada (COMMNT), em caso de


falha, ela deverá ser desfeita (ROLL
BACK). Fluxo básico de uma transação

Observe no diagrama que:

 Toda transação deve começar com a declaração BEGIN TRANSACTION.

 Após o início da transação são executados os diversos comandos de leitura e gravação


(READ/WRITE).

 Se uma operação falhar, será executado o comando de ROLL BACK para desfazer as operações já
realizadas.

 Se todas as operações concluírem com sucesso, o sistema está apenas parcialmente confirmado,
precisa de ser oficialmente confirmado pelo comando COMMIT, pois até o momento, as
informações podem estar apenas no buffer de gravação, e não fisicamente no disco. Após a
finalização do comando COMMIT, todos os dados do buffer estarão armazenados no disco.

 Mesmo processando todas as operações com sucesso, o operador tem a opção de desfazer
essas operações, bastando para isso invocar o comando ROLL BACK.

Dessa forma, podemos concluir que o comando ROLL BACK tanto pode ser invocado por uma falha de
sistema como por uma decisão (escolha) do operador do sistema.

14

2.6.2 - O log do sistema

Para poder recuperar-se de falhas que afetam transações, o sistema mantém um log para registrar todas
as operações de transação que afetam os valores dos itens de banco de dados, bem como outras
informações de transação que podem ser necessárias para permitir a recuperação de falhas.

O log é um arquivo sequencial, apenas para inserção, que é mantido no disco, de modo que não é
afetado por qualquer tipo de falha, exceto por falha de disco ou catastrófica.

Para fins de performance, o arquivo de log pode residir em outro disco diferente do disco de dados
(reveja o módulo sobre sistemas RAID e particionamento para maiores informações).

Normalmente, um (ou mais) buffers de memória mantêm a última parte do arquivo de log, de modo que
as entradas do log são primeiro acrescentadas ao buffer da memória principal. Quando o buffer de log é
preenchido, ou quando ocorrem certas condições (como a execução do comando COMMIT), o buffer de

© 2015 - AIEC - Associação Internacional de Educação Continuada

50
114 – Análise das Demonstrações Financeiras | Unidade 01

log é anexado ao final do arquivo de log no disco. Além disso, operações periódicas de backup copiam o
arquivo de log do disco para outro dispositivo, como uma fita de backup, para proteger contra falhas
catastróficas.

O log funciona registrando o passo a passo de todas as modificações ocorridas no banco de dados,
registrando não só a operação, mas também o horário em que elas ocorrem. Dessa forma, é possível
verificar as alterações feitas bem como voltar o sistema a uma posição exata de data/hora.

15

Há vários tipos de registros de log:

 Start_transaction

Indica que uma transação iniciou sua execução.

 Write_item, valor_antigo, valor_novo

Indica que uma transação mudou o valor do item do banco de dados de valor_antigo para
valor_novo.

 Read_item

Indica que a transação leu o valor do item de banco de dados.

 Commit

Indica que a transação foi concluída com sucesso, e afirma que seu efeito pode ser confirmado
(registrado permanentemente) no banco de dados.

 Abort

Indica que a transação foi abortada.

16

Protocolos para recuperação que evitam propagação de rollbacks (que incluem quase todos os
protocolos práticos) não exigem que operações READ sejam gravadas no log do sistema. Contudo, se o

© 2015 - AIEC - Associação Internacional de Educação Continuada

51
114 – Análise das Demonstrações Financeiras | Unidade 01

log também for usado para outras finalidades, como auditoria (mantendo registro de todas as
operações do banco de dados) então essas entradas podem ser incluídas.

Além disso, alguns protocolos de recuperação que exigem entradas WRITE mais simples só incluem um
valor novo ou valor antigo em vez de incluir ambos.

Observe que não estamos assumindo que todas as mudanças permanentes no banco de dados ocorrem
nas transações, de modo que a noção de recuperação de uma falha de transação equivale a desfazer ou
refazer operações de transação individualmente com base no log. Se o sistema falhar, podemos
recuperar para um estado coerente do banco de dados ao examinar o log e usar uma das técnicas de
recuperação.

Como o log contém um registro de cada operação WRITE que muda o valor de algum item do banco
de dados, é possível desfazer o efeito dessas operações WRITE de uma transação rastreando o log de
volta e retornando todos os itens alterados por uma operação WRITE a seus valores antigos.

Também pode ser necessário refazer uma operação se uma transação


tiver suas atualizações registradas no log, mas houver uma falha
antes que o sistema possa estar certo de que todos esses novos
valores tenham sido gravados no banco de dados real em disco com
base nos buffers da memória principal.

17

2.7 - Ponto de confirmação de uma transação

Uma transação alcança seu ponto de confirmação quando todas as suas operações que acessam o
banco de dados tiverem sido executadas com sucesso e o efeito de todas as operações de transação
no banco de dados tiverem sido registradas no log.

Além do ponto de confirmação, a transação é considerada confirmada, e seu efeito deve ser registrado
permanentemente no banco de dados. A transação então grava um registro de confirmação COMMIT no
log. Se houver uma falha no sistema, podemos pesquisar de volta no log para todas as transações que
gravaram um registro (start_transaction) no log, mas ainda não gravaram seu registro commit. Essas
transações podem ter de ser descartadas (rollback) para desfazer seu efeito sobre o banco de dados
durante o processo de recuperação.

As transações que gravaram seu registro de confirmação no log também devem ter gravado todas as
suas operações WRITE no log, de modo que seu efeito no banco de dados possa ser refeito com base
nos registros de log.

© 2015 - AIEC - Associação Internacional de Educação Continuada

52
114 – Análise das Demonstrações Financeiras | Unidade 01

Observe que o arquivo de log precisa ser mantido no disco. A


atualização de um arquivo do disco envolve copiar o bloco apropriado
do arquivo para um buffer na memória principal, atualizar o buffer na
memória principal e copiar o buffer para o disco.

É comum manter um ou mais blocos do arquivo de log nos buffers da memória principal, chamado
buffer de log, até que eles sejam preenchidos com entradas de log e, depois, gravá-los de volta ao disco
apenas uma vez, ao invés de gravar em disco toda vez que uma entrada de log é acrescentada. Isso
economiza o overhead de várias gravações de disco do mesmo buffer do arquivo de log.

No momento de uma falha do sistema, apenas as entradas de log que foram gravadas de volta para o
disco são consideradas no processo de recuperação, pois o conteúdo da memória principal pode ser
perdido. Logo, antes que uma transação alcance seu ponto de confirmação, qualquer parte do log que
ainda não tenha sido gravada no disco deve agora sê-lo. Esse processo é chamado de gravação forçada
do buffer de log antes da confirmação de uma transação.

18

2.7.1 - Propriedades desejáveis das transações

As transações devem possuir várias propriedades, normalmente chamadas propriedades ACID; elas
devem ser impostas pelos métodos de controle de concorrência e recuperação do SGBD. A seguir estão
listadas as propriedades ACID:

 Atomicidade.

Uma transação é uma unidade de processamento atômica; ela deve ser realizada em sua totalidade
ou não ser realizada de forma alguma.

 Consistência.

Uma transação deve preservar a consistência, significando que, se ela for completamente executada
do início ao fim sem interferência de outras transações, deve levar o banco de dados de um estado
consistente para outro.

 Isolamento.

Uma transação deve parecer como se fosse executada isoladamente de outras transações, embora
muitas delas estejam sendo executadas de maneira simultânea. Ou seja, a execução de uma
transação não deve ser interferida por quaisquer outras transações que acontecem simultaneamente.

© 2015 - AIEC - Associação Internacional de Educação Continuada

53
114 – Análise das Demonstrações Financeiras | Unidade 01

 Durabilidade ou permanência.

As mudanças aplicadas ao banco de dados pela transação confirmada precisam persistir no banco de
dados. Essas mudanças não devem ser perdidas por causa de alguma falha.

19

A propriedade de atomicidade exige que executemos uma transação até o fim. É responsabilidade do
subsistema de recuperação de transação de um SGBD garantir a atomicidade. Se uma transação não for
completada por algum motivo, como uma falha no sistema no meio da execução da transação, a técnica
de recuperação precisa desfazer quaisquer efeitos da transação no banco de dados. Por sua vez, as
operações de gravação de uma transação confirmada devem ser, por fim, gravadas no disco.

A preservação da consistência geralmente é considerada uma responsabilidade dos programadores que


escrevem os programas de banco de dados ou do módulo de SGBD que impõe restrições de integridade.

Lembre-se de que um estado de banco de dados é uma coleção de todos os itens de dados armazenados
(valores) no banco de dados em determinado ponto no tempo. Um estado consistente do banco de
dados satisfaz as restrições especificadas no esquema, bem como quaisquer outras restrições no banco
de dados que devem ser mantidas.

Um programa de banco de dados deve ser escrito de modo que garanta


que, se o banco de dados estiver em um estado consistente antes de
executar a transação, ele estará em um estado consistente depois de
concluir a execução da transação, supondo que não haja interferência em
outras transações.

A propriedade de isolamento é imposta pelo subsistema de controle de concorrência do SGBD. Se cada


transação não tornar suas atualizações (operações de gravação) visíveis para outras transações até que
seja confirmada, uma forma de isolamento é imposta para solucionar o problema da atualização
temporária e eliminar rollback em cascata, mas ela não elimina todos os outros problemas. E por fim, a
propriedade de durabilidade é a responsabilidade do subsistema de recuperação do SGBD.

20

RESUMO
Neste módulo, aprendemos que:

a) Um SGBD controla uma transação de modo a garantir que operações no banco de dados que
sejam formadas duas ou mais ações SQL sejam coordenadas como uma só operação. Caso uma
das operações falhe, o SGBD é capaz de desfazer instruções SQL já realizadas.

© 2015 - AIEC - Associação Internacional de Educação Continuada

54
114 – Análise das Demonstrações Financeiras | Unidade 01

b) O termo operação serializada refere-se ao controle em série de operações, em que a CPU tem o
poder de fracionar o processamento de uma operação em várias partes, e assim atender a
várias solicitações de processamento, sem precisar que uma se encerre completamente para o
início de outra.

c) O processo paralelo real só ocorre quando há duas ou mais CPUs em um computador.

d) Uma transação pode conter uma ou mais operações de acesso a dados.

e) Somente os comandos de manipulação de dados, DML, podem ser controlados por transação.

f) A instrução begin transaction (ou start transaction) inicia uma transação. A instrução commit
transaction (ou end transaction) encerra uma transação. A instrução rollback cancela uma
transação desfazendo as operações realizadas.

g) Os buffers de banco de dados controlam os dados (em blocos) a serem armazenados no disco.
Portanto, operações DML geralmente permanecem um tempo no buffer antes de ser
armazenadas em disco. Somente após a execução do comando commit é que há a garantia de
que o dado foi realmente armazenado no disco.

h) Há vários problemas relacionados à concorrência de dados. A atualização perdida refere-se a


duas operações alterando o mesmo dado ao mesmo tempo. A atualização temporária (ou
leitura suja) refere-se a uma operação que está lendo um dado que está sendo modificado por
outra transação ao mesmo tempo, sendo que a segunda transação é cancelada. O problema do
resumo incorreto diz respeito às funcionalidades de agregação (como funções MAX, MIN e
AVG), que durante o cálculo de agregação tem os dados alterados por outra operação. O
problema da leitura não repetitiva ocorre quando uma transação que precisa ler o mesmo item
duas vezes, e antes de ler a segunda vez ocorre uma mudança no valor do dado.

i) Há diversos tipos de falhas que podem ocasionar a necessidade de recuperação (desfazimento)


de uma transação. Entre elas: falhas de hardware (algum problema no computador), falhas de
software (algum problema no software que gerencia a solução de TI como um todo) e falhas de
rede. No processamento de uma transação pode ocorrer um erro lógico, como uma divisão por
zero. Podem ocorrer ainda erros de acesso ou até mesmo problemas advindos de agentes
externos, como incêndios, enchentes ou sabotagens.

j) Ao se invocar o comando COMMIT, os blocos de dados alterados, que estão no buffer, são
descarregados para os discos. Somente após a conclusão da gravação de todos os blocos é que o
comando COMMIT se encerra.

k) O log é um arquivo sequencial, apenas para inserção, que é mantido no disco.

l) O log também é usado pelo subsistema de recuperação para voltar o sistema a um momento
anterior, desfazendo operações no banco de dados.

© 2015 - AIEC - Associação Internacional de Educação Continuada

55
114 – Análise das Demonstrações Financeiras | Unidade 01

m) As quatro propriedades de uma transação são: Atomicidade (ser realizada totalmente),


Consistência (não pode ser interferida e deve deixar o banco de dados consistente), Isolamento
(não deve interferir em outras transações) e Durabilidade (seu resultado deve persistir).

UNIDADE 2 – ESTRUTURAS DE ARQUIVO AUXILIARES

MÓDULO 4 – CONTROLE DE CONCORRÊNCIA


01

1 - TÉCNICAS DE BLOQUEIO EM DUAS FASES


No conteúdo anterior, vimos as características das transações, os critérios ACID e os comandos SQL que
gerenciam uma transação. Vimos também como o log de dados é utilizado para gerenciamento das
operações de dados, bem como para a eventual necessidade de desfazer as operações já realizadas.

Agora veremos como o controle de concorrência pode evitar ou gerar problemas transacionais.

O objetivo do controle de concorrências é garantir a não interferência ou isolamento das transações


executadas simultaneamente.

Estudaremos a técnica de bloqueio de registro, que impede que múltiplas transações acessem o mesmo
item de dado ao mesmo tempo.

Algumas das principais técnicas usadas para controlar a execução concorrente de transações são
baseadas no conceito de bloqueio de itens de dados.

Um bloqueio é uma variável associada a um item de dados que descreve o status do item em relação
a possíveis operações SQL que podem ser aplicadas a ele.

Em geral, existe um bloqueio para cada item de dados no banco de dados. Os bloqueios são utilizados
como um meio de sincronizar o acesso por transações concorrentes aos itens do banco de dados.

Há basicamente duas técnicas de bloqueio:

 o bloqueio binário e

 o bloqueio compartilhado.

© 2015 - AIEC - Associação Internacional de Educação Continuada

56
114 – Análise das Demonstrações Financeiras | Unidade 01

02

2 - BLOQUEIO BINÁRIO
Um bloqueio binário, como o próprio nome diz, confere ao item de dados apenas dois estados:
bloqueado ou desbloqueado.

Quando um item de dados está bloqueado, nenhuma operação SQL pode ser feita nele, nem mesmo
leitura. Já quando o item de dados está desbloqueado, qualquer operação SQL pode ser feita.

O bloqueio binário é conferido por meio de um bit de acesso a cada item de dado, de cada campo, de
cada tabela. Esse bit pode assumir os valores 0 (desbloqueado) ou 1 (bloqueado). O gerenciamento
dessa técnica de bloqueio é feito por um bit de controle em cada item de dado do banco de dados
(cada campo, de cada registro de cada tabela).

Normalmente, o estado de cada item de dado do banco de dados é 0, ou seja, todos os dados estão
acessíveis. Entretanto, quando uma transação é iniciada (start transaction), os itens de dados a serem
consultados ou modificados são identificados e há a alteração do bit de acesso para 1, de forma que
somente essa transação em execução pode acessar aquele(s) item(ns) de dado. Para as demais
transações, o acesso é negado. Após a conclusão da transação (comando commit ou rollback), o bit é
resetado, ou seja, volta a ser 0, liberando o acesso ao item de dado.

Caso uma transação tente acessar um item de dado bloqueado,


ela entra em espera, e um tempo determinado pela configuração
do sistema (SGBD) começa a ser contado. Caso o tempo se
esgote sem que a transação inicial tenha desbloqueado o item de
dados, a segunda transação recebe uma exceção de erro do tipo
“time out” (expirado o prazo de espera). Caso a transação inicial
se encerre e libere o acesso antes do prazo de time out, a
segunda transação então é executada. Saiba+

Saiba+

Apesar de, estatisticamente falando, o tempo de espera médio de uma transação ser de poucos
milissegundos, os prazos comuns de time out são configurados entre 10 segundos a um minuto.
Entretanto, sistemas específicos podem ter qualquer valor configurado para o time out, como 1
segundo ou 1 hora. O subsistema gerenciador de bloqueio do SGBD é quem registra e controla os
bloqueios dos itens de dados.

© 2015 - AIEC - Associação Internacional de Educação Continuada

57
114 – Análise das Demonstrações Financeiras | Unidade 01

03

O gerenciamento dos bloqueios (de todos os tipos) é feito por meio de uma tabela especial de
sistema. Essa tabela reside no banco de dados de gerenciamento do SGBD e normalmente não é
acessível pelo usuário. Uma vez que o item de dado é desbloqueado, a informação sobre o bloqueio
dele é excluída da tabela de registro de bloqueios.

A técnica do bloqueio compartilhado, que iremos estudar a seguir, também utiliza tabelas de sistema
para o registro de bloqueios, de forma que, para evitar a repetição, não iremos citar essa informação
novamente.

A grande desvantagem do bloqueio binário é que, uma vez bloqueado, o item de dado não pode nem
ao menos ser lido, mesmo que ele não esteja sendo alterado.

Veja o exemplo a seguir:

Suponha uma transação T1 fazendo uma leitura da tabela de Notas_Alunos para atualizar a tabela
Historico_Escolar. Essa transação faz a leitura das notas registradas, computa as médias e lança-as no
histórico escolar. Durante a execução dessa transação T1, aplicando o boqueio binário, outra transação
T2 que desejasse apenas ler dados de notas de alunos, não poderia fazê-lo, visto que T1 bloqueou as
tabelas Notas_Alunos e Historico_Escolar.

Devido à restrição simplista que esse tipo de controle faz, os SGBDs mais modernos não utilizam essa
técnica, por ser considerada tecnologicamente ultrapassada. Veremos a seguir outra forma, mais
moderna e inteligente, de contornar esse problema.

04

3 - BLOQUEIO COMPARTILHADO
A técnica de bloqueio compartilhado, também denominada bloqueio exclusivo, traz consigo a
vantagem de bloquear apenas os itens de dados que sofrerão alteração, mantendo os demais itens
de dados, que são usados apenas para leitura, disponíveis para as demais transações.

Hoje, todos os SGBDs modernos utilizam essa técnica de bloqueio.

O esquema de bloqueio binário que explicamos é muito restritivo para itens de banco de dados porque,
no máximo, uma transação pode manter um bloqueio em determinado item. Devemos permitir que
várias transações acessem um mesmo item de dados, caso todas elas acessem esse item de dados

© 2015 - AIEC - Associação Internacional de Educação Continuada

58
114 – Análise das Demonstrações Financeiras | Unidade 01

apenas para fins de leitura. Isso porque as operações de leitura no mesmo item por diferentes
transações não estão em conflito.

Contudo, se uma transação tiver de gravar um determinado item de dado, ela precisa ter acesso
exclusivo a ele. Para essa finalidade, um tipo diferente de bloqueio é utilizado. Nesse esquema,
denominado de bloqueio compartilhado (ou exclusivos, ou ainda denominado de bloqueio de
leitura/gravação), existem três operações de bloqueio:

 Read_lock(X);

 Write lock(X);

 Unlock(X).

Read_lock(X)

Bloqueia o item para leitura (e consequentemente para gravação também). Esse bloqueio é desejado
para um item de dados que será alterado pela transação. Não será possível ler o item de dado até que
o mesmo seja liberado (desbloqueado).

Write lock(X)

É um bloqueio menos restritivo do que o anterior, permite ler o item de dado, mas não alterá-lo.
Dessa forma, outras transações podem ler o item de dados, mesmo que a transação inicial ainda
esteja sendo executada. Nenhuma outra transação poderá ler o dado até que o mesmo seja
desbloqueado.

Unlock(X)

Este comando desbloqueia um dos dois tipos de bloqueio apresentado. Permite que outras
transações possam controlar o item de dado, efetuando, por exemplo, um dos dois tipos de bloqueio
citados. Esse comando geralmente é aplicado no fim da transação, seja pelo comando commit ou pelo
comando rollback.

05

Dessa forma, podemos dizer que um determinado item de dados pode possuir três estados possíveis:

© 2015 - AIEC - Associação Internacional de Educação Continuada

59
114 – Análise das Demonstrações Financeiras | Unidade 01

 bloqueado para leitura,

 bloqueado para gravação ou

 desbloqueado.

Um item bloqueado para leitura também é chamado de bloqueado para compartilhamento, pois outras
transações podem ler o item, enquanto um item bloqueado para gravação é chamado bloqueado
exclusivo, visto que uma única transação mantém exclusivamente o bloqueio no item.

Um método para implementar as operações anteriores em um bloqueio de leitura/gravação é registrar


o número de transações que mantêm um bloqueio compartilhado (leitura) em um item na tabela de
bloqueio (conforme explicado no item bloqueio binário). Cada registro na tabela de bloqueio terá os
seguintes campos:

 ID do item dado;

 Tipo de bloqueio;

 ID das transações dependentes e pendentes de processamento;

 ID da transação principal.

ID do item dado

Identificação (ponteiro) do item de dado que está bloqueado.

Tipo de bloqueio

Indica se o bloquei é de leitura ou de gravação.

ID das transações dependente e pendentes de processamento

Lista que identifica as transações que estão aguardando a execução da transação principal acontecer
(e desbloquear o item) para serem executadas na sequência.

ID da transação principal

Transação principal que está bloqueando o item de dado.

© 2015 - AIEC - Associação Internacional de Educação Continuada

60
114 – Análise das Demonstrações Financeiras | Unidade 01

06

Se um determinado item de dado está bloqueado para gravação (permitindo a leitura) e outras
transações só efetuam leituras, então essas transações não constarão na lista de transações pendentes.
Nesse caso, esta lista só contém transações que necessitam de gravação.

Veja o resumo a seguir:

 Se a transação principal efetuar um bloqueio de gravação, então a lista de transações


pendentes só pode ser de transações de gravação também, visto que transações que apenas
leem o item de dado não estão bloqueadas.

 Se a transação principal efetuar um bloqueio de leitura e gravação, então a lista de


transações pendentes pode ser de transações de leitura ou de gravação também, visto que
nenhuma outra transação tem acesso ao item de dado enquanto este estiver bloqueado pela
transação principal.

Vejamos um exemplo prático:

a) Uma transação T1 está alterando o nome de um aluno na tabela ALUNO. Essa transação t1
precisa bloquear o item de dado “nome do aluno” até que a alteração do dado seja concluída.
Nesse momento, nenhuma outra transação poderá ler o nome do aluno ou mesmo alterá-lo.
Neste caso, estamos tratando de um bloqueio de leitura e gravação. Ao terminar de executar a
transação T1, o bloqueio será desfeito e outras transações poderão ocorrer.

b) Agora, uma transação T2 está lendo o nome de um outro aluno na tabela ALUNO. Enquanto
essa transação T2 não for concluída, nenhuma outra transação poderá alterar o nome do aluno,
entretanto, outras transações podem também ler o nome do aluno, pois, neste caso, o bloqueio
desejado é apenas o de gravação.

07

Dessa forma, toda transação precisa realizar as seguintes operações:

© 2015 - AIEC - Associação Internacional de Educação Continuada

61
114 – Análise das Demonstrações Financeiras | Unidade 01

Se o item de
Ao iniciar sua
Toda transação dado estiver
execução, toda
precisa verificar bloqueado, a
transação deve
inicialmente se transação precisa Ao terminar a
criar um
um item de dado verificar o tipo transação, o item
bloqueio
está bloqueado de bloqueio para de dado deve ser
adequado, seja
ou não antes de saber se pode desbloqueado.
ele de leitura ou
poder ser executar ou se
de
executada. deve aguardar o
leitura/gravação.
desbloqueio.

Algumas falhas de sistema podem impedir o desbloqueio adequado de um


item de dado ao término de uma transação. Para isso, rotinas especiais de
gerenciamento do SGBD verificam periodicamente se há itens de dados
bloqueados sem uma transação acontecendo. Ao encontrar uma
divergência, essa rotina é capaz de desbloquear o item de dado.

Configurações de tempo de processamento gerenciam o tempo que uma transação fica aguardando a
liberação do bloqueio de um item de dado. Normalmente, o bloqueio de um item de dado dura poucos
milissegundos. Dessa forma, se uma transação ficar aguardando muito tempo, por exemplo, cerca de 30
segundos para ser executada, pode ser gerado um erro de tempo de processamento (timeout) e a
transação será cancelada.

08

4 - CONVERSÃO E SERIALIZAÇÃO DE BLOQUEIO


Uma rotina possível de se acontecer é um item de dado bloqueado precisar mudar de tipo de bloqueio
durante uma transação que contempla mais de uma operação. Nesse tipo de situação, uma transação
pode iniciar um bloqueio de gravação de um item de dados durante a execução da operação A (uma
operação de SELECT sobre o item de dado), mas depois precisar mudar o bloqueio desse mesmo item de
dados para um bloqueio de leitura/gravação para a execução de uma operação B (uma operação de
UPDATE).

Dessa forma, antes de ocorrer o desbloqueio do item de dados (o que liberaria outras transações), há
uma mudança do estado de bloqueio do item.

Também é possível a mudança oposta, ou seja, um item de dados ter inicialmente um bloqueio de
leitura/gravação e depois esse bloqueio mudar apenas para bloqueio de gravação, liberando outras
transações que irão realizar apenas leitura do item.

© 2015 - AIEC - Associação Internacional de Educação Continuada

62
114 – Análise das Demonstrações Financeiras | Unidade 01

09

A serialização é a capacidade de o SGBD organizar todas as transações pendentes de forma que uma
transação de maior prioridade não dependa de uma transação de menor prioridade.

Isso garante que a sequência pela qual as transações irão ser processadas não geram dependências por
outras transações que estão aguardando o processamento.

Para que a serialização funcione perfeitamente, uma transação precisa seguir o protocolo de bloqueio
em duas fases. Esse protocolo rege que as transações se comportem da seguinte maneira:

Durante a primeira fase, denominada fase


A segunda fase é denominada de fase de
de expansão, ou fase de crescimento, a
encolhimento. Nesta fase nenhum novo
transação irá criar novos bloqueios a itens
bloqueio pode ser feito, e os bloqueios
de dados. Nessa fase, nenhum bloqueio
existentes serão liberados. Nesta fase
poderá ser liberado. Nesta fase também
também poderá ocorrer a conversão de
poderá ocorrer a conversão de um
um bloqueio de gravação/leitura em um
bloqueio de gravação (permite ler) para
bloqueio de gravação.
um bloqueio de gravação/leitura.

A funcionalidade de gerenciamento do schedule (agendamento) usa os estados e as fases das


transações pendentes para serializar corretamente as transações de forma a não gerar dependências
entre transações em execução e transações aguardando processamento. O protocolo de bloqueio, ao
impor as regras de bloqueio em duas fases, também impõe a serialização.

10

4.1 - Deadlocks

O deadlock (impasse) ocorre quando uma transação A está esperando por algum item que está
bloqueado por uma transação B, e esta transação B está esperando por algum item que está
bloqueado na transação A. Logo, ambas transações permanecem pausadas, aguardando que uma
delas libere o bloqueio em um item de dados.

Mas como a relação é mútua, nunca ocorrerá o bloqueio do item. Desta forma, ambas as transações
ficam impossibilitadas de serem processadas.

Uma das formas de se evitar esse problema é usando um protocolo de prevenção de deadlock. Esse
protocolo é utilizado no bloqueio de duas fases e funciona sobre a seguinte regra:

© 2015 - AIEC - Associação Internacional de Educação Continuada

63
114 – Análise das Demonstrações Financeiras | Unidade 01

Uma transação X não pode criar bloqueios a itens de dados e houver outras transações em execução
que utilizem itens de dados bloqueados pela transação X.

Ou seja, ao criar um bloqueio, o protocolo verifica que esse item de dado a ser bloqueado está na
iminência de ser utilizado por alguma outra transação. Se houver algum item de dado nessa situação, o
protocolo impede a criação do bloqueio. Mas a transação X não é cancelada, ela fica aguardando a
execução das demais transações até que nenhuma das transações pendentes utilize algum item de dado
desta transação. Feito isso, ocorre o bloqueio normal dos itens de dados que ela precisa.

Outra técnica para tratar um deadlock baseia-se na funcionalidade de detecção de deadlock. Nesse
modelo, os deadlocks podem ocorrer, e a funcionalidade irá escolher uma das transações para abortá-la.
Geralmente, a transação mais antiga tem prioridade, e a mais nova é, consequentemente, abortada.

A última técnica para tratar deadlock é por meio do uso de timeouts, onde, a partir de um determinado
tempo limite de espera de processamento, a transação é automaticamente cancelada.

11

Concluindo:

Durante a execução das transações, as tabelas de sistema de controle transacional são utilizadas para o
controle do bloqueio dos itens de dados. Ao término da conclusão das transações, os registros são
apagados das tabelas de bloqueio e as transações são gravadas nos arquivos de Log.

As técnicas que vimos neste módulo são fundamentais para o controle transacional. Esse controle tanto
é usado para permitir o compartilhamento do uso do banco de dados com vários usuários, quanto
também nas eventuais necessidades de recuperação do banco de dados.

Por fim, o bloqueio de itens só faz sentido para itens que já existam no banco de dados, operações de
inserção de dados não requerem bloqueios. Já, uma operação de exclusão de dados pode estar sendo
bloqueada se o registro a ser excluído está sendo bloqueado por outra transação.

12

RESUMO
Neste módulo, aprendemos que:

a) O controle de concorrência de acesso aos itens de dados é feito por meio de técnicas de
bloqueio de acesso.
b) As técnicas mais comuns de bloqueio são bloqueio binário e bloqueio compartilhado.

© 2015 - AIEC - Associação Internacional de Educação Continuada

64
114 – Análise das Demonstrações Financeiras | Unidade 01

c) Um bloqueio de dados é gerenciado no SGBD por meio de tabelas de sistema onde cada registro
representa o item de dado bloqueado e o tipo de bloqueio.

d) A técnica de bloqueio binário possui apenas dois estados: 1 - item bloqueado (onde qualquer
acesso é impedido) e 0 - item desbloqueado (onde qualquer tipo de acesso é permitido). O
gerenciamento dessa técnica de bloqueio é feito por um bit de controle em cada item de dado
do banco de dados (cada campo, de cada registro de cada tabela).

e) A técnica de bloqueio compartilhado, também denominada bloqueio exclusivo, traz consigo a


vantagem de bloquear apenas os itens de dados que sofrerão alteração, mantendo os demais
itens de dados que são usados apenas para leitura disponíveis para as demais transações.

f) Há três comandos básicos para o bloqueio compartilhado: read lock (bloqueia o item para
leitura), write lock (bloqueia o item para gravação, mas permite a leitura), unlock (desbloqueia o
item).

g) Uma tabela especial de sistema controla os itens de dados bloqueados e as transações


pendentes.

h) Para efetivar um bloqueio, uma transação precisa: a) verificar se o item de dados está
bloqueado; b) aguardar o desbloqueio ou bloquear o item; c) desbloquear o item ao término da
transação.

i) Por meio da conversão de bloqueio, podemos mudar o tipo de bloqueio compartilhado de um


item de dado, seja de apenas leitura para leitura/gravação, como o oposto.

j) A serialização é a capacidade de o SGBD organizar todas as transações pendentes de forma que


uma transação de maior prioridade não dependa de uma transação de menor prioridade.

k) Durante uma transação, o processo do bloqueio ocorre em duas fases, uma de expansão, onde
os bloqueios são criados e uma de encolhimento, onde os bloqueios são liberados.

l) O SGBD utiliza o gerenciamento do schedule para serializar corretamente as transações a fim de


não gerar dependências.

m) Quando duas transações criam dependências entre si, ocorre o que chamamos de deadlock.
Quando isso ocorre, o SGBD possui mecanismos de cancelar uma das transações, no intuído de
resolver o deadlock. Um dos mecanismos é baseado em controle de tempo de processamento
(timeout).

© 2015 - AIEC - Associação Internacional de Educação Continuada

65

Você também pode gostar