Pagine

domenica 8 settembre 2013

SQL Server 2014 CTP1 : In-Memory Optimized Tables, No Lock and Latch !!!

Fino all'edizione 2012 il meccanismo di controllo delle transazioni faceva largo uso di Lock e di Latch, con tutti i problemi derivanti alla loro gestione
(Consumo di risorse, low performance, etc.... )
Le In-Memory Optimized Tables introdotte da SQL Server 2014 CTP1 utilizzano un meccanismo di gestione accessi concorrenziali di tipo Optimistic Multiversion,
che consente alle transazioni di essere Lock e Latch Free.

Ciò non significa assolutamente che le transazioni implementate sulle in-Memory Optimized Tables non siano
Atomic
Consistency
Isolation
Durability

Vediamo un esempio di funzionamento.

Creo un Database di test

Use Master
Go

CREATE DATABASE Hekaton_Test     
ON PRIMARY(NAME = [PRIMARY],     
   FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\Hekaton_Test\Hekaton_DiskBasedTable.mdf')
   ,FILEGROUP [SampleDB_mod_fg] 
    CONTAINS MEMORY_OPTIMIZED_DATA    
     (NAME = [HKDB_mod_dir],FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\Hekaton_Test\In_Memory_Table')
LOG ON (name = [SampleDB_log], Filename='C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\Hekaton_Test\Hekaton_Test_log.ldf')  
Go

Use Hekaton_Test
Go

Create table MemoryTable
(
 id int not null PRIMARY KEY NONCLUSTERED HASH WITH(BUCKET_COUNT = 1024)
 ,Campo char(30) not null
)WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA); 
GO

;With Cte as(Select 1 Riga union All Select 1)
 ,Cte4 as (Select A.Riga From Cte A, Cte B)
 ,Cte16 as (Select A.Riga From Cte4 A, Cte4 B)
 ,Cte256 as (Select A.Riga From Cte16 A, Cte16 B)
 ,Cte65536 as (Select A.Riga From Cte256 A, Cte256 B)
 ,Results as (Select ROW_NUMBER()Over(Order by Riga) Riga From Cte65536)
Insert into MemoryTable(id, Campo)
Select Riga
       ,Riga
from Results where Riga <= 1024

Simulo l'accesso di due connessioni alla medesima tabella, la prima eseguirà una transazione in update di tutte le righe, la seconda contemporaneamente tenterà la lettura dell'intera tabella.

Questa la transazione

USE Hekaton_Test

BEGIN TRANSACTION

UPDATE MemoryTable WITH(SNAPSHOT) SET campo = 'T1 ' + campo 

SELECT * FROM MemoryTable WITH(SNAPSHOT)
 
L'aggiornamento è andato a buon fine

e la select all'interno della prima connessione ha ovviamente restituito i valori modificati.

N.B. Senza WITH(SNAPSHOT) l'update e la select della prima connessione restituirebbero un errore.
Nella MSDN trovate tutte le info sull'utilizzo degli Isolation Level con le In-Memory Optimized Tables.

La prima transazione è attualmente attiva dato che il COMMIT ancora non è stato implementato.
Cosa succede se la seconda connessione tenta la lettura della tabella ?

SELECT * FROM MemoryTable

Dato che le In-Memory Optimized tables utilizzano un sistema Optimistic Multiversion non ho lock e di conseguenza no wait, quindi i dati vengono restituiti senza attesa nella loro versione pre-modifica.


N.B. Il multiversioning per le In-Memory Optimized Tables non utilizza il TempDb ma la RAM.

Ovviamente chiudendo con il COMMIT la transazione che ha implementato l'update tutte le successive letture restituiranno i dati modificati.

Ma cosa accade quando 2 transazioni tentano di modificare i medesimi dati contemporaneamente ?

Non avendo ancora effettuato il commit posso eseguire subito una nuova transazione che implementerà una modifica.

USE Hekaton_Test

BEGIN TRANSACTION

UPDATE MemoryTable WITH(SNAPSHOT) SET campo = 'T2 ' + campo 

SELECT * FROM MemoryTable WITH(SNAPSHOT)

ed ecco il risultato

 
In questo caso si verifica un conflitto e la transazione viene conclusa con errore.
In casi come questo è necessario ritentare la transazione.
Qui trovate le linee guida per il retry delle transazioni.
Qui trovate le linee guida sulla selezione dell'isolation level.

Ciao

Luca

Nessun commento:

Posta un commento