Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Escalação de bloqueio do SQL Server

Introdução


Os bancos de dados relacionais seguem as propriedades ACID na forma como implementam transações – Atomicidade, Consistência, Isolamento e Durabilidade. O isolamento é necessário para garantir que múltiplas transações não possam causar alterações nos dados e deixar os eventuais resultados inconsistentes. Para garantir que as operações permaneçam isoladas, o SQL Server aplica mecanismos de Locking.

Modos de bloqueio e hierarquia


O mecanismo do SQL Server para controle de simultaneidade está envolvido. Para otimizar o desempenho em termos de esperas de bloqueio, impasses e similares, você precisa tomar uma decisão com base no cenário específico.

No SQL Server, os bloqueios podem ser mantidos de várias maneiras e em vários níveis de granularidade. Modos de bloqueio são as maneiras específicas de fazer isso, e seus níveis são Hierarquia de bloqueio.

A Figura 1 mostra os modos de bloqueio disponíveis no SQL Server para o nível de isolamento de transação padrão (READ COMMITTED):

Visão geral do escalonamento de bloqueio


O SQL Server pode bloquear recursos em vários níveis. Depende dos atos mais eficientes de acordo com a natureza da carga de trabalho. A Tabela 1 mostra os recursos que podem ser bloqueados.
  • Os bloqueios em um nível mais granular (por exemplo, bloqueios de nível de linha) permitem maior simultaneidade e menos bloqueio.
  • Os bloqueios em um nível superior (por exemplo, bloqueio no nível da tabela) reduzem a simultaneidade. Eles podem causar mais bloqueios, dependendo de quanto tempo dura a instrução real.

O SQL Server escolhe o nível de bloqueio necessário de acordo com as métricas internas.

Um escalonamento de bloqueio ocorre quando um bloqueio é convertido de um nível mais fino de granularidade para um nível mais grosseiro.

Por exemplo, converter um bloqueio de linha em um bloqueio de tabela (consulte a Tabela 1).
Recurso Descrição
RID O identificador de linha usado para bloquear uma única linha em um heap.
CHAVE O bloqueio de linha em um índice usado para proteger intervalos de chaves em transações serializáveis.
PÁGINA A página de 8 kilobytes (KB) em um banco de dados, como páginas de dados ou de índice.
EXTENSÃO O grupo contíguo de oito páginas, como páginas de dados ou de índice.
HoBT A pilha ou árvore B. O bloqueio está protegendo uma árvore B (índice) ou as páginas de dados de heap em uma tabela que não possui um índice clusterizado.
TABELA A tabela inteira, incluindo todos os dados e índices.
ARQUIVO O arquivo de banco de dados.
APLICATIVO O recurso especificado pelo aplicativo.
METADADOS Bloqueios de metadados.
ALLOCATION_UNIT A unidade de alocação.
BANCO DE DADOS Todo o banco de dados.

A justificativa para o escalonamento de bloqueio


Bloqueios no SQL Server podem ser bastante caros. Para cada bloqueio adquirido pelo Lock Manager, o SQL Server deve reservar memória – 64 bytes ou 128 bytes. A quantidade depende se estamos lidando com um sistema de 32 bits ou 64 bits, respectivamente.

À medida que o número de bloqueios de linha em uma tabela aumenta, o SQL Server deve adquirir cada vez mais memória. Assim, outros processos estão morrendo de fome, sem memória.

Faz sentido converter bloqueios de linha e bloqueios de página em um único bloqueio de nível de tabela (objeto). Isso acontece quando o número de bloqueios para essa tabela excede 5.000.

O comprometimento ocorre quando a tabela inteira não está mais disponível para outras sessões no processo de transação.

Demonstrando o escalonamento de bloqueio


Podemos demonstrar o Lock Escalation usando o código na Listagem 1.

Vamos primeiro descrever um pouco a tabela. Produção.ProdutosI é uma tabela relativamente pequena com cerca de 7.777 linhas. Os elementos de construção são o mesmo conjunto de 77 linhas duplicadas 101 vezes. O Código na Listagem 1 consiste em três versões da mesma instrução de atualização, cada uma incluída em uma transação.
-- Listing 1: Demonstrating Lock Escalation

-- Update very few rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';

ROLLBACK

-- Update a large number of rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';

ROLLBACK

-- Update over 5000 rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';

ROLLBACK 

Para maior clareza, detalharemos o conteúdo da Listagem 1.

Antes disso, vamos observar a Listagem 2 – uma consulta para exibir os bloqueios mantidos no banco de dados TSQLV4.

Nossa primeira ação é executar a Listagem 1a. Em seguida, usamos a Listagem 2 para examinar como o Lock Manager realiza o bloqueio no cenário. Executamos a Listagem 1a sem emitir a instrução rollback. Dessa forma, preservamos os bloqueios por tempo suficiente para que a consulta na Listagem 2 possa capturá-los.
-- Listing 1a: Demonstrating Lock Escalation
-- Update very few rows

BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice='18.00';

ROLLBACK

-- Listing 2: Displaying Locks Held in Database TSQLV4

USE TSQLV4
GO
SELECT 
resource_type
, DB_NAME (resource_database_id) database_name
--, OBJECT_NAME(resource_associated_entity_id) resource_name
, request_mode
, request_type
, request_status
, request_reference_count
, request_session_id
, resource_associated_entity_id
, OBJECT_NAME(resource_associated_entity_id) [object_name] --small obj ids
, getuser.login_name
FROM sys.dm_tran_locks
CROSS APPLY dmv.dbo.getuser(request_session_id) as getuser
WHERE DB_NAME (resource_database_id)='TSQLV4';

Quando executamos a consulta na Listagem 1a e, em seguida, verificamos os bloqueios usando a consulta na Listagem 2, o SQL Server retorna o resultado mostrado na Figura 2.

404 linhas na tabela têm unitprice='18.00' . O Lock Manager bloqueia essas linhas junto com os outros bloqueios de qualquer nível necessário. Ele traz a contagem de linhas da Figura 2 para 467.
-- Listing 1b: Demonstrating Lock Escalation
-- Update a large number of rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00'
WHERE unitprice>'18.00';

ROLLBACK

Observamos um comportamento semelhante quando executamos a consulta na Listagem 1b. Desta vez, estamos lidando com 4406 linhas. Ele reflete o número de linhas na tabela Production.ProductI com preço unitário>18,00.
-- Listing 1c: Demonstrating Lock Escalation
-- Update over 5000 rows
BEGIN TRAN

use TSQLV4
GO
UPDATE Production.ProductsI SET unitprice='100.00';

ROLLBACK

Quando avançamos e executamos o código na Listagem 1c, vemos um comportamento diferente (veja a Figura 4).

A listagem 1c tenta atualizar todas as 7777 linhas na tabela Production.ProductI. O SQL Server determina que bloquear tantas linhas não é mais eficiente para garantir o isolamento. Em vez disso, a tabela inteira está bloqueada.

Mais sobre escalonamento de bloqueio


O bloqueio da tabela implica que nenhuma outra sessão pode modificar suas linhas pela duração da transação, o que pode acontecer mesmo quando uma sessão de bloqueio não manipula todas as linhas da tabela.

Também vale a pena mencionar que outros fatores podem afetar como os bloqueios são adquiridos e escalados no SQL Server. Esses são o nível de isolamento configurado, indexação e sinalizadores de rastreamento.

Os sinalizadores de rastreamento T1211 e T1224 podem ser aplicados para desabilitar totalmente o escalonamento de bloqueio. O escalonamento de bloqueio também pode ser desabilitado e habilitado para uma tabela específica com o seguinte código:
-- Listing 5: Disable and Enable Lock Escalation

ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=DISABLE);

ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=TABLE);

Pode-se querer fazê-lo para reduzir o bloqueio associado ao bloqueio de toda a tabela. Por causa do impacto na memória, deve ser considerado em uma medida temporária.

Conclusão


O SQL Server usa o Lock Escalation para controlar o impacto de um bloqueio mais granular nos recursos do servidor. Para exibir a forma de ocorrência desses bloqueios – bloqueios de linha, bloqueios de página, bloqueios de objeto, etc. – consulte a exibição de gerenciamento dinâmico sys.dm_tran_locks. Ele fornece muitas informações sobre travamento, além do Lock Escalation.

Embora seja possível manipular o comportamento do Lock Manager, é essencial fazê-lo com muito cuidado. Também é crucial conhecer o impacto preciso no desempenho de qualquer esforço direcionado a fazer tais modificações.

Referências

  1. Korotkevitch, D., 2016. Pro SQL Server Internals. Flórida:Dmitri Korotkevitch
  2. Cenários de bloqueio usando Sys.dm_tran_locks
  3. Guia de bloqueio de transações e controle de versão de linha