Home > News > Breaking News > SQL Server 2025 Optimized Locking Internals: Gestione dei lock in aggiornamenti concorrenti

SQL Server 2025 Optimized Locking Internals: Gestione dei lock in aggiornamenti concorrenti

Optimized Locking è una funzionalità dell’Engine di SQL Server 2025, è stata implementata per ridurre l’utilizzo della memoria impiegata per la gestione dei lock, ridurre il fenomeno noto con il nome di lock escalation e aumentare la concorrenza dei carichi di lavoro.

In questo articolo abbiamo descritto il funzionamento generale di Optimized Locking, ora passiamo alla pratica, osservando come l’Engine gestisce aggiornamenti concorrenti con Lock After Qualification. Consideriamo la tabella dbo.SalesOrder in un database SQL Server 2025 con Optimized Locking completamente abilitato. La tabella contiene i seguenti dati di prova.

SalesOrderIDStatusSalesOrderNumberCustomerIDTotalDue
1NSO-100011231500
2PSO-100021232200
3NSO-10003123450
4SSO-10004124800
5CSO-10005125600
dbo.SalesOrder

Consideriamo i seguenti UPDATE sulla tabella dbo.SalesOrder: una sessione di lavoro (sessione 1) esegue un primo UPDATE; mentre la transazione è ancora attiva, una seconda sessione di lavoro (sessione 2) tenta di aggiornare le stesse righe.

Come gestirà la situazione con Optimized Locking attivo?

-- Sessione 1
BEGIN TRANSACTION
UPDATE
  [dbo].[SalesOrder]
SET
  Status = 'S'
WHERE
  (CustomerID = 123)
  AND (TotalDue > 1000);

-- Sessione 2
BEGIN TRANSACTION
UPDATE
  [dbo].[SalesOrder]
SET
  Status = 'C'
WHERE
  (CustomerID = 123)
  AND (TotalDue > 1000);
GO

Entrambi gli UPDATE coinvolgono le stesse righe. Osserviamo quindi i lock attivi con la DMV sys.dm_tran_locks la sessione 1 ha lo SPID 156, mentre la sessione 2 ha lo SPID 149.

SELECT
  resource_type
  ,resource_database_id
  ,resource_description
  ,request_mode
  ,request_type
  ,request_status
  ,request_session_id
  ,resource_associated_entity_id
FROM
  sys.dm_tran_locks
WHERE
  request_session_id IN (156, 149)
  AND resource_type IN ('PAGE', 'RID', 'KEY', 'XACT');

La figura seguente illustra i lock acquisiti dai comandi di UPDATE.

Nella prima riga, il lock acquisito dalla sessione 1 (SPID 156) sul TID è facilmente riconoscibile. Osservando la seconda riga, però, sorge una domanda: perché SQL Server richiede un lock di tipo Shared (S) sul TID invece di un lock di tipo Update (U), che sembrerebbe più appropriato per un’operazione di aggiornamento?

Per rispondere, è necessario comprendere la semantica dei lock sui TID e in che modo differisce da quella dei lock tradizionali (U/X/IX) applicati alle righe.

Semantica dei lock tradizionali

Nel modello classico, il lock di tipo Update (U) serve a evitare deadlock read-write (esempio due sessioni che leggono la stessa riga e poi entrambe vogliono aggiornarla), viene convertito in lock di tipo Exclusive (X) sulle righe qualificate per le modifiche. Il lock di tipo Shared (S) è utilizzato per le letture condivise, bloccato da altri X lock.

Semantica nel modello TID Locking

Con SQL Server 2025, i lock su risorse XACT non rappresentano blocchi su dati, ma dipendenze tra transazioni, quindi un lock di tipo Shared (S) su XACT non serve a proteggere dati condivisi, ma a monitorare lo stato di un’altra transazione. È un “wait handle” interno che SQL Server usa per sapere quando quella transazione termina. In altre parole il lock Shared posto sul TID che ha modificato le righe è passivo: non blocca, ma osserva. Quando la transazione proprietaria del TID viene completata (COMMIT o ROLLBACK), l’Engine rilascia il XACT lock e la seconda transazione viene svegliata. L’attesa viene tracciata con il wait type LCK_M_S_XACT_MODIFY.

L’attributo virtuale %%lockres%% , disponibile anche nelle versioni precedenti, mostra l’identificatore di lock (lock resource string) associato a ciascuna riga della tabella; vediamo gli identificatori di lock per le righe della tabella dbo.SalesOrder con la query seguente.

SELECT
  %%lockres%% AS [Lockres]
  ,*
FROM
  [dbo].[SalesOrder];
LockresSalesOrderIDStatusSalesOrderNumberCustomerIDTotalDue
(8194443284a0)1NSO-100011231500
(61a06abd401c)2PSO-100021232200
(98ec012aa510)3NSO-10003123450
(a0c936a3c965)4SSO-10004124800
(59855d342c69)5CSO-10005125600
dbo.SalesOrder con %%lockres%%

Si osservi che l’identificatore (8194443284a0) è lo stesso citato nella colonna resource_description della DMV sys.dm_tran_locks. La sessione 2, quella con SPID 149, sta aspettando sul Transaction ID che detiene la riga identificata dal lock hash (8194443284a0), la prima delle due righe modificate.

Perché non un Update lock?

Un Update (U) lock avrebbe senso solo se il lock rappresentasse una potenziale modifica futura di una risorsa condivisa. Ma in questo caso:

  • La risorsa non è la riga, ma il Transaction ID
  • Non c’è alcun rischio di “upgrade conflict” (solo una transazione può avere quel TID)
  • Non esistono U lock semantici sulle risorse di tipo XACT ma solo S e X

Dal punto di vista del lock manager, un Update (U) lock non avrebbe alcun significato operativo su una risorsa di tipo XACT. La scelta di Microsoft di usare uno Shared (S) lock deriva da una logica interna: “sto aspettando di leggere lo stato della transazione che detiene quella riga”, non “mi preparo a modificarla”.

Riqualifica o restart

Dopo che la transazione bloccante è terminata, SQL Server rilegge la riga per verificare se è cambiata (il TID indica se c’è stata modifica). Se la riga è cambiata viene riqualificata rispetto alla condizione WHERE. Se l’operatore non supporta la riqualificazione, SQL Server riavvia l’intera query. Se la riga non è stata cambiata (il TID è lo stesso di prima e i dati sono identici), la riqualifica non avviene, viene acquisito un lock di tipo Exclusive (X) sulla riga, quest’ultima viene aggiornata e il lock rilasciato immediatamente dopo l’aggiornamento.

Conclusioni

Ciò che può sembrare un comportamento insolito, come la richiesta di un S lock su un TID, riflette in realtà la logica interna di Optimized Locking. SQL Server 2025 ottimizza così la gestione dei lock durante gli aggiornamenti concorrenti, bilanciando correttamente consistenza, scalabilità e performance.

Chi è Sergio Govoni

Sergio Govoni è laureato in Scienze e Tecnologie Informatiche. Da oltre 16 anni lavora presso una software house che produce un noto sistema ERP, distribuito a livello nazionale ed internazionale, multi azienda client/server su piattaforma Win32. Attualmente si occupa di progettazione e analisi funzionale, coordina un team di sviluppo ed è responsabile tecnico di prodotto. Lavora con SQL Server dalla versione 7.0 e si è occupato d'implementazione e manutenzione di database relazionali in ambito gestionale, ottimizzazione delle prestazioni e problem solving. Nello staff di UGISS si dedica alla formazione e alla divulgazione in ambito SQL Server e tecnologie a esso collegate, scrivendo articoli e partecipando come speaker ai workshop e alle iniziative del primo e più importante User Group Italiano sulla tecnologia SQL Server. Ha conseguito la certificazione MCP, MCTS SQL Server. Per il suo contributo nelle comunità tecniche e per la condivisione della propria esperienza con altri, dal 2010 riceve il riconoscimento SQL Server MVP (Microsoft Most Valuable Professional). Nel corso dell'anno 2011 ha contribuito alla scrittura del libro SQL Server MVP Deep Dives Volume 2 (http://www.manning.com/delaney/).

Leggi Anche

SQL Server 2025 Optimized Locking: TID internals

Optimized Locking è una funzionalità dell’Engine di SQL Server 2025, è stata implementata per ridurre …

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

− two = three

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.