Condividi tramite


Esempio di livello di isolamento basato sul controllo delle versioni delle righe

Nell'esempio seguente vengono illustrate le differenze tra le transazioni di isolamento dello snapshot e le transazioni Read commited che utilizzano il controllo delle versioni delle righe.

[!NOTA]

Prima di esaminare gli esempi, è importante comprendere i livelli di isolamento basati sul controllo delle versioni delle righe. Vedere Informazioni sui livelli di isolamento basati sul controllo delle versioni delle righe e Utilizzo di livelli di isolamento basati sul controllo delle versioni delle righe.

Esempi

A. Utilizzo dell'isolamento dello snapshot

In questo esempio una transazione di isolamento dello snapshot legge dati che verranno successivamente modificati da un'altra transazione. La transazione snapshot non blocca l'operazione di aggiornamento eseguita dall'altra transazione e continua a leggere dati dalla riga con versione, ignorando la modifica dei dati. Quando, tuttavia, la transazione snapshot tenta di modificare dati che sono già stati modificati da un'altra transazione, viene generato un errore e la transazione snapshot termina.

Nella sessione 1:

USE AdventureWorks;
GO

-- Enable snapshot isolation on the database.
ALTER DATABASE AdventureWorks
    SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

-- Start a snapshot transaction
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
GO

BEGIN TRANSACTION;
    -- This SELECT statement will return
    -- 48 vacation hours for the employee.
    SELECT EmployeeID, VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

Nella sessione 2:

USE AdventureWorks;
GO

-- Start a transaction
BEGIN TRANSACTION;
    -- Subtract a vacation day from employee 4.
    -- Update is not blocked by session 1 since
    -- under snapshot isolation shared locks are
    -- not requested.
    UPDATE HumanResources.Employee
        SET VacationHours = VacationHours - 8
        WHERE EmployeeID = 4;

-- Verify that the employee now has 40 vacation hours.
    SELECT VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

Nella sessione 1:

    -- Reissue the SELECT statement - this shows
    -- the employee having 48 vacation hours.  The
    -- snapshot transaction is still reading data from
    -- the versioned row.
SELECT EmployeeID, VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

Nella sessione 2:

-- Commit the transaction; this commits the data
-- modification.
COMMIT TRANSACTION;
GO

Nella sessione 1:

    -- Reissue the SELECT statement - this still 
    -- shows the employee having 48 vacation hours
    -- even after the other transaction has committed
    -- the data modification.
SELECT EmployeeID, VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

    -- Because the data has been modified outside of the
    -- snapshot transaction, any further data changes to 
    -- that data by the snapshot transaction will cause 
    -- the snapshot transaction to fail. This statement 
    -- will generate a 3960 error and the transaction will 
    -- terminate.
    UPDATE HumanResources.Employee
        SET SickLeaveHours = SickLeaveHours - 8
        WHERE EmployeeID = 4;

-- Undo the changes to the database from session 1. 
-- This will not undo the change from session 2.
ROLLBACK TRANSACTION
GO

B. Utilizzo di Read commited con il controllo delle versioni delle righe

In questo esempio una transazione Read committed che utilizza il controllo delle versioni delle righe viene eseguita simultaneamente a un'altra transazione. La transazione Read committed si comporta in modo diverso da una transazione snapshot. Come una transazione snapshot, la transazione Read committed legge le righe con versione anche dopo che i dati sono stati modificati dall'altra transazione. A differenza di una transazione snapshot, tuttavia, la transazione Read committed:

  • Legge i dati modificati dopo che l'altra transazione ha eseguito il commit delle modifiche dei dati.

  • È in grado di aggiornare i dati modificati dall'altra transazione, a differenza della transazione snapshot.

Nella sessione 1:

USE AdventureWorks;
GO

-- Enable READ_COMMITTED_SNAPSHOT on the database.
-- For this statement to succeed, this session
-- must be the only connection to the AdventureWorks
-- database.
ALTER DATABASE AdventureWorks
    SET READ_COMMITTED_SNAPSHOT ON;
GO

-- Start a read-committed transaction
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO

BEGIN TRANSACTION;
    -- This SELECT statement will return
    -- 48 vacation hours for the employee.
    SELECT EmployeeID, VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

Nella sessione 2:

USE AdventureWorks;
GO

-- Start a transaction
BEGIN TRANSACTION;
    -- Subtract a vacation day from employee 4.
    -- Update is not blocked by session 1 since
    -- under read-committed using row versioning shared locks are
    -- not requested.
    UPDATE HumanResources.Employee
        SET VacationHours = VacationHours - 8
        WHERE EmployeeID = 4;

-- Verify that the employee now has 40 vacation hours.
    SELECT VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

Nella sessione 1:

    -- Reissue the SELECT statement - this still shows
    -- the employee having 48 vacation hours.  The
    -- read-committed transaction is still reading data 
    -- from the versioned row and the other transaction 
    -- has not committed the data changes yet.
SELECT EmployeeID, VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

Nella sessione 2:

-- Commit the transaction
COMMIT TRANSACTION;
GO

Nella sessione 1:

    -- Reissue the SELECT statement which now shows the 
    -- employee having 40 vacation hours.  Being 
    -- read-committed, this transaction is reading the 
    -- committed data.  This is different from snapshot
    -- isolation which reads from the versioned row.
    SELECT EmployeeID, VacationHours
        FROM HumanResources.Employee
        WHERE EmployeeID = 4;

    -- This statement, which caused the snapshot transaction 
    -- to fail, will succeed with read-committed using row versioning.
    UPDATE HumanResources.Employee
        SET SickLeaveHours = SickLeaveHours - 8
        WHERE EmployeeID = 4;

-- Undo the changes to the database from session 1. 
-- This will not undo the change from session 2.
ROLLBACK TRANSACTION;
GO