Bloqueio de intervalo de chave
O bloqueio de intervalo de chave protege uma gama de linhas implicitamente inclusas em um conjunto de registros que são lidos por uma instrução Transact-SQL , ao mesmo tempo em que utiliza o nível de isolamento de transação serializável. O nível de isolamento serializável requer que qualquer consulta executada durante uma transação deva obter o mesmo conjunto de linhas, toda vez que seja executada durante a transação. Um bloqueio de intervalo de chave protege esse requisito, impedindo que outras transações insiram novas linhas cujas chaves falhariam no intervalo de chaves lido pela transação serializável.
O bloqueio de intervalo de chave impede leituras fantasmas. Ao proteger os intervalos de chaves entre as linhas, ele também evita inserções fantasmas em um conjunto de registros acessado por uma transação.
Um bloqueio de intervalo de chave é colocado em um índice, especificando um valor de chave inicial e final. Esse bloqueio impede quaisquer tentativas de inserção, atualização ou exclusão de qualquer linha de um valor de chave que falhe no intervalo, pois essas operações primeiro teriam que obter um bloqueio no índice. Por exemplo, uma transação serializável pode emitir uma instrução SELECT que leia todas as linhas cujos valores das chaves estejam entre 'AAA' e 'CZZ'. Um bloqueio no intervalo de chave sobre o valor da chave de**'AAA'** até 'CZZ' evita que outras transações insiram linhas com valores de chave em qualquer posição daquele intervalo, tais como 'ADG', 'BBD', ou 'CAL'.
Modos de bloqueio de intervalo de chave
O bloqueio de intervalo de chave inclui um intervalo e um componente de linha especificados no formato intervalo-linha:
O intervalo representa o modo de bloqueio que protege o intervalo entre duas entradas consecutivas de índice.
A fila representa o modo de bloqueio que protege a entrada de índice.
O modo representa o modo de bloqueio combinado em uso. Os modos de bloqueio de intervalo de chave consistem de duas partes. A primeira representa o tipo de bloqueio utilizado para impedir o intervalo de índice (RangeT), e a segunda representa o tipo de bloqueio utilizado para impedir uma chave específica (K). As duas partes são conectadas por um hífen (-), como por exemplo IntervaloT-K.
Intervalo
Linha
Modo
Descrição
RangeS
S
RangeS-S
Intervalo compartilhado, bloqueio de recurso compartilhado; varredura de intervalo serializável.
RangeS
U
RangeS-U
Intervalo compartilhado, bloqueio de recurso compartilhado; varredura de intervalo serializável.
RangeI
Null
RangeI-N
Insere o intervalo, anula o bloqueio de recurso; usado para testar intervalos antes de inserir uma nova chave em um índice.
RangeX
X
RangeX-X
Intervalo exclusivo, bloqueio de recurso exclusivo; usado ao atualizar uma chave em um intervalo.
Observação |
---|
O modo de bloqueio interno Nulo é compatível com todos os outros modos de bloqueio. |
Os modos de bloqueio de intervalo de chave têm uma matriz de compatibilidade que mostra quais bloqueios são compatíveis com outros bloqueios obtidos em chaves e intervalos sobrepostos. Para ver a matriz completa de compatibilidade de bloqueios, consulte Compatibilidade de Bloqueio.
|
Modo concedido existente |
|
|
|
|
|
|
---|---|---|---|---|---|---|---|
Modo solicitado |
S |
U |
X |
RangeS-S |
RangeS-U |
RangeI-N |
RangeX-X |
Compartilhado (S) |
Sim |
Sim |
Não |
Sim |
Sim |
Sim |
Não |
Atualizar (U) |
Sim |
Não |
Não |
Sim |
Não |
Sim |
Não |
Exclusivo (X) |
Não |
Não |
Não |
Não |
Não |
Sim |
Não |
RangeS-S |
Sim |
Sim |
Não |
Sim |
Sim |
Não |
Não |
RangeS-U |
Sim |
Não |
Não |
Sim |
Não |
Não |
Não |
RangeI-N |
Sim |
Sim |
Sim |
Não |
Não |
Sim |
Não |
RangeX-X |
Não |
Não |
Não |
Não |
Não |
Não |
Não |
Bloqueios de Conversão
Os bloqueios de conversão são criados quando um bloqueio de intervalo de chave se sobrepuser a outro bloqueio.
Bloqueio 1 |
Bloqueio 2 |
Bloqueio de Conversão |
---|---|---|
S |
RangeI-N |
RangeI-S |
U |
RangeI-N |
RangeI-U |
X |
RangeI-N |
RangeI-X |
RangeI-N |
RangeS-S |
RangeX-S |
RangeI-N |
RangeS-U |
RangeX-U |
Os bloqueios de conversão podem ser observados por um curto período de tempo sob diferentes circunstâncias complexas, às vezes enquanto executando processos simultâneos.
Varredura de Intervalo Serializável, Busca de Singleton, Exclusão e Inserção
O bloqueio de intervalo de chave garante que as seguintes operações sejam serializáveis:
Consulta de varredura de intervalo
Busca de singleton em linha inexistente
Operação de exclusão
Operação de Inserção
Antes que o bloqueio de intervalo de chave possa ocorrer, as seguintes condições devem ser satisfeitas:
O nível de isolamento da transação deve ser definido como SERIALIZABLE.
O processador de consulta deve usar um índice para implementar o predicado de filtro do intervalo. Por exemplo, a cláusula WHERE em uma instrução SELECT poderia estabelecer uma condição de intervalo com esse predicado: ColumnX BETWEEN N**'AAA'** E N**'CZZ'.** Um bloqueio de intervalo de chave só pode ser adquirido se a ColumnX estiver coberta por uma chave de índice .
Exemplos
A seguinte tabela e índice são usados como base para os exemplos de intervalo de chave que seguem.
Consulta de Varredura de Intervalo
Para garantir que uma consulta de varredura de intervalo seja serializável, a mesma consulta deve retornar os mesmos resultados a cada vez que seja executada dentro de uma mesma transação. Novas linhas não devem ser inseridas dentro da consulta de varredura de intervalo por outras transações; caso contrário, elas se tornam inserções fantasmas. Por exemplo, a consulta seguinte usa a tabela e índice da ilustração anterior:
SELECT name
FROM mytable
WHERE name BETWEEN 'A' AND 'C';
Os bloqueios de intervalo de chave são posicionados nas entradas do índice correspondentes ao intervalo das linhas de dados, onde o nome está entre os valores Adam e Dale, evitando que novas linhas que se qualifiquem na consulta anterior sejam acrescentadas ou exclusas. Embora o primeiro nome desse intervalo seja Adam, o bloqueio de intervalo de chave RangeS-S dessa entrada de índice garante que nenhum nome novo começando com a letra A possa ser adicionado antes de Adam, como por exemplo Abigail. De forma semelhante, o bloqueio de intervalo de chave RangeS-S na entrada do índice garante que nenhum nome novo começando com a letra C possa ser adicionado depois de Carlos, como Clive por exemplo.
Observação |
---|
O número de bloqueios que RangeS-S contém é n+1, onde n é o número de linhas que satisfazem a consulta. |
Busca Singleton de Dados Inexistentes
Se uma consulta dentro de uma transação tenta selecionar uma fila que não existe, a emissão da consulta em um momento posterior dentro da mesma transação terá que retornar o mesmo resultado. Nenhuma outra transação terá permissão de inserir essa linha inexistente. Por exemplo, nessa consulta:
SELECT name
FROM mytable
WHERE name = 'Bill';
Um bloqueio de intervalo de chave é posicionado na entrada de índice correspondendo ao intervalo de nome de Ben a Bing pois o nome Bill seria inserido entre essas duas entradas adjacentes. O bloqueio de intervalo de chave do modo RangeS-S é posicionado na entrada de índice Bing. Isso impede que qualquer outra transação insira valores, como Bill, entre as entradas de índice Ben e Bing.
Operação de Exclusão
Ao excluir um valor dentro de uma transação, o intervalo no qual o valor se encaixa não tem que ser bloqueado durante a transação que está executando a operação de exclusão. Bloquear o valor de chave excluso até o fim da transação é suficiente para manter a serialização. Por exemplo, na seguinte instrução DELETE:
DELETE mytable
WHERE name = 'Bob';
Um bloqueio (X) exclusivo é posicionado na entrada de índice correspondente ao nome Bob. Outras transações podem inserir ou excluir valores entre ou após o valor excluído Bob. Entretanto, qualquer transação que tente ler, inserir, ou excluir o valor Bob será bloqueada até que a transação de exclusão seja confirmada ou revertida.
A exclusão de intervalo pode ser executada utilizando três modos básicos de bloqueio: de linha, de página, ou de tabela. A estratégia de bloqueio de linha, página, ou tabela, é decidida pelo otimizador de consultas, ou pode ser especificada pelo usuário através de dicas como ROWLOCK, PAGLOCK, ou TABLOCK. Quando PAGLOCK ou TABLOCK são usadas, o Mecanismo de Banco de Dados desaloca imediatamente uma página de entrada, se todas as linhas dessa página forem exclusas. Por outro lado, quando ROWLOCK é usada, todas as linhas exclusas são marcadas apenas como exclusas; elas são depois removidas da página de índice usando-se uma tarefa em segundo plano.
Operação de Inserção
Ao inserir um valor dentro de uma transação, o intervalo no qual o valor se encaixa não tem que ser bloqueado durante a transação que está executando a operação de inserção. Bloquear o valor da chave inserida até o término da transação é suficiente para manter a serialização. Por exemplo, na seguinte instrução INSERT:
INSERT mytable VALUES ('Dan');
O bloqueio de intervalo de chave no modo RangeI-N é posicionado na entrada de índice correspondente ao nome David, para testar o intervalo. Se o bloqueio é concedido, Dan é inserido, e um bloqueio (X) exclusivo é posicionado no valor Dan. O bloqueio de intervalo de chave no modo RangeI-N, só é necessário para testar o intervalo, e não é mantido durante a transação que executa a operação de inserção. Outras transações podem inserir ou excluir valores antes ou após o valor inserido Dan. Entretanto, qualquer transação que tente ler, inserir, ou excluir o valor Dan será bloqueada até que a transação de inserção seja confirmada ou revertida.