Переключите уровень изоляции с SNAPSHOT на активную транзакцию и запустите DDL - PullRequest
2 голосов
/ 24 сентября 2019

Я хотел бы заставить MS SQL Server использовать уровень изоляции SNAPSHOT, но в той же транзакции я должен запустить операции DML и DDL.Как я знаю, мы не можем запустить DDL (большую часть операции DDL) в транзакции с уровнем изоляции SNAPSHOT.

В статье https://docs.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017 мы можем прочитать

Еслитранзакция начинается с уровня изоляции SNAPSHOT, вы можете изменить его на другой уровень изоляции и затем вернуться к SNAPSHOT.Транзакция запускается при первом обращении к данным.

Поэтому моя идея - запустить транзакцию с уровнем изоляции SNAPSHOT, выполнить DML, а затем переключить транзакцию на уровень изоляции READ COMMITTED, и здесь возникает проблема.

/* the problematic part */
EXEC print_curr_il 'on start'
SET TRANSACTION ISOLATION LEVEL SNAPSHOT
EXEC print_curr_il 'after setting il to snapshot'

BEGIN TRAN 
    EXEC print_curr_il 'before inserting'
    INSERT INTO tbl2 VALUES ('some value')  
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    EXEC print_curr_il 'after setting il to read committed'
    ALTER TABLE tbl1 ADD val int
COMMIT

/* simple tables */
CREATE TABLE [dbo].[tbl1](
    [text] [nchar](10) NULL
)
GO

CREATE TABLE [dbo].[tbl2](
    [text] [nchar](10) NULL
)
GO

/* procedeure to print current isolation level */
CREATE PROCEDURE [dbo].[print_curr_il]
    @desc varchar(50)
AS
BEGIN
    Declare @il varchar(50);
    SELECT @il = 
        CASE transaction_isolation_level 
            WHEN 0 THEN 'Unspecified' 
            WHEN 1 THEN 'ReadUncommitted' 
            WHEN 2 THEN 'ReadCommitted' 
            WHEN 3 THEN 'Repeatable' 
            WHEN 4 THEN 'Serializable' 
            WHEN 5 THEN 'Snapshot'
        END 
    FROM sys.dm_exec_sessions where session_id = @@SPID;
    print @desc + ' Isolation Level = ' + @il;
END
GO

В результате я получаю

on start Isolation Level = ReadCommitted
after setting il to snapshot Isolation Level = Snapshot
before inserting Isolation Level = Snapshot

(1 row affected)
after setting il to read committed Isolation Level = ReadCommitted
Msg 3964, Level 16, State 1, Line 11
Transaction failed because this DDL statement is not allowed inside a snapshot isolation transaction. Since metadata is not versioned, a metadata change can lead to inconsistency if mixed within snapshot isolation.

Так что это выглядит невозможным, но я не могу найти строгий ответ, что это невозможно.

Я подозреваючто SET TRANSACTION ISOLATION LEVEL ... в открытой транзакции меняет поведение блокировки, но не на весь тип транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...