Introduzione
I database relazionali seguono le proprietà ACID nel modo in cui implementano le transazioni:Atomicità, Coerenza, Isolamento e Durabilità. L'isolamento è necessario per garantire che più transazioni non possano causare modifiche ai dati e lasciare gli eventuali risultati incoerenti. Per garantire che le operazioni rimangano isolate, SQL Server applica meccanismi di blocco.
Modalità di blocco e gerarchia
È coinvolto il meccanismo di SQL Server per il controllo della concorrenza. Per ottimizzare le prestazioni in termini di attese di blocco, deadlock e simili, è necessario prendere una decisione in base allo scenario specifico.
In SQL Server, i blocchi possono essere mantenuti in vari modi ea diversi livelli di granularità. Le modalità di blocco sono i modi specifici per farlo e i loro livelli sono la gerarchia di blocco.
La figura 1 mostra le modalità di blocco disponibili in SQL Server per il livello di isolamento delle transazioni predefinito (READ COMMITTED):
Panoramica dell'escalation dei blocchi
SQL Server può bloccare le risorse a diversi livelli. Dipende dagli atti più efficienti in base alla natura del carico di lavoro. La tabella 1 mostra le risorse che possono essere bloccate.
- I blocchi a un livello più granulare (ad es., i blocchi a livello di riga) consentono una maggiore concorrenza e un minor numero di blocchi.
- I blocchi a un livello superiore (ad es. Blocco a livello di tabella) riducono la concorrenza. Potrebbero causare più blocchi, a seconda della durata dell'istruzione effettiva.
SQL Server sceglie il livello di blocco necessario in base alle metriche interne.
Un'escalation del blocco si verifica quando un blocco viene convertito da un livello di granularità più fine a un livello più grossolano.
Ad esempio, convertire un blocco di riga in un blocco di tabella (vedere la tabella 1).
Risorsa | Descrizione |
RID | L'identificatore di riga utilizzato per bloccare una singola riga all'interno di un heap. |
CHIAVE | Il blocco di riga all'interno di un indice utilizzato per proteggere gli intervalli di chiavi nelle transazioni serializzabili. |
PAGINA | La pagina da 8 kilobyte (KB) in un database, ad esempio dati o pagine di indice. |
ESTENSIONE | Il gruppo contiguo di otto pagine, come dati o pagine di indice. |
HoBT | L'heap o B-tree. Il blocco protegge un albero B (indice) o le pagine di dati dell'heap in una tabella che non dispone di un indice cluster. |
TABELLA | L'intera tabella, inclusi tutti i dati e gli indici. |
FILE | Il file di database. |
APPLICAZIONE | La risorsa specificata dall'applicazione. |
METADATI | Blocchi metadati. |
UNITÀ_ALLOCAZIONE | L'unità di allocazione. |
BANCA DATI | L'intero database. |
La motivazione per l'escalation dei blocchi
I blocchi in SQL Server possono essere piuttosto costosi. Per ogni blocco acquisito da Lock Manager, SQL Server deve riservare memoria:64 byte o 128 byte. L'importo dipende dal fatto che si tratti rispettivamente di un sistema a 32 o 64 bit.
Con l'aumento del numero di blocchi di riga in una tabella, SQL Server deve acquisire sempre più memoria. Quindi, altri processi stanno morendo di fame, senza memoria.
Ha senso convertire i blocchi di riga e di pagina in un blocco a livello di singola tabella (oggetto). Succede quando il numero di blocchi per quella tabella supera 5000.
Il compromesso si verifica quando l'intera tabella non è più disponibile per altre sessioni nel processo di transazione.
Dimostrazione dell'escalation del blocco
Possiamo dimostrare l'escalation dei blocchi utilizzando il codice nel Listato 1.
Descriviamo prima un po' il tavolo. Produzione.ProdottiI è una tabella relativamente piccola che contiene circa 7777 righe. Gli elementi dell'edificio sono lo stesso insieme di 77 righe duplicate 101 volte. Il Codice nel Listato 1 è costituito da tre versioni della stessa dichiarazione di aggiornamento, ciascuna racchiusa in una transazione.
-- 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
Per maggiore chiarezza, analizzeremo il contenuto del Listato 1.
Prima di ciò, osserviamo il Listato 2, una query per visualizzare i blocchi contenuti nel database TSQLV4.
La nostra prima azione è eseguire il Listato 1a. Quindi, utilizziamo il Listato 2 per esaminare come Lock Manager esegue il blocco nello scenario. Eseguiamo il Listato 1a senza emettere l'istruzione di rollback. In questo modo, conserviamo i blocchi abbastanza a lungo, in modo che la query nel Listato 2 possa catturarli.
-- 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 eseguiamo la query nel Listato 1a e quindi controlliamo i blocchi utilizzando la query nel Listato 2, SQL Server restituisce il risultato mostrato nella Figura 2.
404 righe nella tabella hanno unitprice='18.00' . Il Lock Manager blocca queste righe insieme agli altri lock di qualsiasi livello necessario. Porta il conteggio delle righe della figura 2 a 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
Osserviamo un comportamento simile quando eseguiamo la query nel Listato 1b. Questa volta abbiamo a che fare con 4406 righe. Riflette il numero di righe sulla tabella Production.ProductI con prezzo unitario>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 andiamo oltre ed eseguiamo il codice nel Listato 1c, vediamo un comportamento diverso (vedi Figura 4).
Il listato 1c tenta di aggiornare tutte le 7777 righe nella tabella Production.ProductI. SQL Server determina che il blocco di così tante righe non è più efficiente per garantire l'isolamento. Invece, l'intero tavolo è bloccato.
Ulteriori informazioni sull'escalation dei blocchi
Il blocco della tabella implica che nessun'altra sessione può modificare le proprie righe per la durata della transazione, il che può verificarsi anche quando una sessione di blocco non manipola tutte le righe della tabella.
Vale anche la pena ricordare che altri fattori possono influenzare il modo in cui i blocchi vengono acquisiti ed escalation in SQL Server. Questi sono il livello di isolamento configurato, l'indicizzazione e i flag di traccia.
I flag di traccia T1211 e T1224 possono essere applicati per disabilitare completamente l'escalation dei blocchi. L'escalation del blocco può anche essere disabilitata e abilitata per una tabella specifica con il codice seguente:
-- Listing 5: Disable and Enable Lock Escalation
ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=DISABLE);
ALTER TABLE Production.ProductsI SET (LOCK_ESCALATION=TABLE);
Si potrebbe volerlo fare per ridurre il blocco associato al blocco dell'intera tabella. A causa dell'impatto sulla memoria, dovrebbe essere considerato su una misura temporanea.
Conclusione
SQL Server utilizza l'escalation dei blocchi per controllare l'impatto di un blocco più granulare sulle risorse del server. Per visualizzare il modo in cui si verificano questi blocchi – blocchi di riga, blocchi di pagina, blocchi di oggetti, ecc. – interrogare la vista a gestione dinamica sys.dm_tran_locks. Fornisce molte informazioni sul blocco, oltre all'escalation del blocco.
Sebbene sia possibile manipolare il comportamento di Lock Manager, è essenziale farlo con grande attenzione. È inoltre fondamentale conoscere l'impatto preciso sulle prestazioni di qualsiasi sforzo diretto ad apportare tali modifiche.
Riferimenti
- Korotkevitch, D., 2016. Componenti interni di Pro SQL Server. Florida:Dmitri Korotkevitch
- Blocca scenari utilizzando Sys.dm_tran_locks
- Guida al blocco delle transazioni e al controllo delle versioni delle righe