O nível de isolamento serializável do SQL Server bloqueia a tabela inteira

9

Eu e um colega meu discutimos as implicações do uso do nível de isolamento serializável. Ele disse que bloqueava a tabela inteira, mas eu discordei disso dizendo que potencialmente poderia, mas tenta aplicar bloqueios de intervalo e não aplica serialização verdadeira, conforme explicado aqui: O nível de isolamento serializável .

Também não consigo encontrar nada nos documentos para a "tabela inteira de bloqueios": SET TRANSACTION ISOLATION LEVEL .

O documento declara várias coisas sobre bloqueios de intervalo, portanto, em teoria, você pode bloquear a tabela inteira simplesmente com um bloqueio de intervalo que bloqueia todo o intervalo de valores possíveis na tabela, mas não bloqueia a tabela.

Estou completamente errado aqui? De fato, bloqueia toda a tabela (ou tabelas)?

mslot
fonte

Respostas:

16

Escalada, no entanto

A escalação de bloqueio no nível de isolamento serializável pode ocorrer da mesma forma que ocorre com outros níveis de isolamento.

  • Índices corretos podem ajudar a evitar o escalonamento de bloqueios até um ponto
  • O bloqueio de muitos índices aumentará a probabilidade de escalação de bloqueios; a contagem é cumulativa entre objetos para uma única instrução

Alguns exemplos rápidos usando uma única tabela com um único índice. Id é a chave primária e o índice clusterizado na tabela.

Uma linha

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

UPDATE c
SET c.Score = 2147483647 
FROM dbo.Comments AS c
WHERE c.Id = 138; --One value

ROLLBACK

Para um único valor de ID, o bloqueio é mínimo.

+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X     | Comments      | KEY           |           1 |
| IX           | Comments      | OBJECT        |           1 |
| IX           | Comments      | PAGE          |           1 |
+--------------+---------------+---------------+-------------+

Linhas múltiplas

Mas os bloqueios subirão se começarmos a trabalhar em intervalos:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

UPDATE c
SET c.Score = 2147483647 
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 5000; -- Small range

ROLLBACK

Agora, temos mais bloqueios exclusivos em mais chaves:

+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X     | Comments      | KEY           |        2429 |
| IX           | Comments      | OBJECT        |           1 |
| IX           | Comments      | PAGE          |          97 |
+--------------+---------------+---------------+-------------+

Way More Rows

Isso continuará até atingirmos um ponto de inflexão:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN

UPDATE c
SET c.Score = 2147483647 
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 11655; --Larger range

ROLLBACK

A escalação de bloqueio é tentada e é bem-sucedida:

+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| X            | Comments      | OBJECT        |           1 |
+--------------+---------------+---------------+-------------+

Preste atenção

É importante separar dois conceitos aqui: o nível de isolamento será serializável, independentemente do tipo de bloqueio. A consulta escolhe o nível de isolamento e o mecanismo de armazenamento escolhe os bloqueios. Serializable nem sempre resulta em bloqueios de intervalo - o mecanismo de armazenamento pode escolher qualquer tipo de bloqueio que ainda atenda ao nível de isolamento.

Erik Darling
fonte
5

Se houver um índice em um predicado de pesquisa, ele poderá ser usado para bloqueios de intervalo .

Ou seja, trave da primeira linha para a próxima no intervalo. E a partir da próxima para a terceira linha, etc. Até a última linha do intervalo. Então, basicamente, vários bloqueios de linha, mas bloqueiam o intervalo de inserções também para valores "intermediários" (bloqueando o intervalo).

Para que isso aconteça, você (SQL Server) precisa ter um índice para trabalhar. Sem índices para fazer o bloqueio (índices em predicados), você (pelo que sei) obterá bloqueios de tabela.

Tibor Karaszi
fonte