ALLOW_SNAPSHOT_ISOLATION і READ_COMMITTED_SNAPSHOT


38

Більшість форумів та прикладів в Інтернеті завжди пропонують встановити обидва ALLOW_SNAPSHOT_ISOLATIONта READ_COMMITTED_SNAPSHOTвстановити значення УВІМКНЕНО, коли хтось задає знімок, версію рядків чи подібне запитання.

Я думаю, що слово SNAPSHOT в обох налаштуваннях стає трохи заплутаним. Я подумав, що для того, щоб двигун бази даних використовував версію версій замість блоків для поведінки за замовчуванням READ_COMMITTED, база даних READ_COMMITTED_SNAPSHOTвстановлюється на УВІМКНЕНО незалежно від того, які ALLOW_SNAPSHOT_ISOLATIONпараметри.

Цей ALLOW_SNAPSHOT_ISOLATIONпараметр встановлено на УВІМКНЕНО, щоб дозволити ізоляцію знімків під час запуску транзакції (наприклад, НАСТРОЙКА ІЗОЛЯЦІЇ РОЗВИТКУ ІЗОЛЯЦІЇ), незалежно від READ_COMMITTED_SNAPSHOTналаштування.

Єдиною причиною встановлення цих двох параметрів є УВІМКНЕНО - це коли потрібно прочитати версію версії рядків І ізоляцію знімків.

Моє запитання: чи моє розуміння якимось чином неправильне? І що ці два параметри повинні бути завжди встановлені на УВІМКНЕНО (особливо для ПРОЧИТАНОГО ЗАВДАННЯ версій)?

Відповіді:


25

Ваше розуміння правильне. Це стає трохи заплутано.

Кім Трипп (один з програмістів SQL Server і невід'ємна частина SQLSkills) проходить саме те, що ви заявили у відео MCM на Snapshot Isolation . Швидкий перехід на 41:45 у відео, щоб перейти до тієї частини, де вона відповідає на ваше запитання.

Якщо ви використовуєте, ALLOW_SNAPSHOT_ISOLATIONпереконайтеся, що ви використовуєте SET TRANSACTION ISOLATION LEVEL SNAPSHOTу своєму коді, інакше ви не отримаєте жодної переваги.

Якщо ви встановили SET READ_COMMITTED_SNAPSHOT ON, не потрібно змінювати жоден код. MS SQL Server автоматично застосовує ізоляцію знімків для цієї таблиці.

Я не перевіряв, що станеться, якщо ви запитаєте інший рівень ізоляції у вашому коді, я підозрюю, що він замінить цю опцію, але спершу протестуйте її.

Швидкий погляд на ефективність роботи за допомогою знімка Snapshot.

Хороша стаття про те, як ізоляція знімків може змінити очікувану поведінку вашої програми . Він показує приклади того, як оператор оновлення та оператор select можуть повертати абсолютно різні та несподівані результати.


Дякуємо за посилання Як і інші BOL, вона обговорювала ці дві установки незалежно та колективно (саме там вона стає трохи заплутаною, або, можливо, я над цим думаю). Мені довелося перевірити це, щоб краще зрозуміти.
Тревіс

4
Це чудова відповідь, і я хотів би лише уточнити пару пунктів. По-перше, якщо ви просто скануєте відео, почніть з 23:18, а також з 41:45. Ранній час додає більше деталей. Хоча Кім згадує відповідь на оригінальне запитання, все ще існує потреба змінити код, якщо використовувати обидва. Read_Committed_Snapshot - ізоляція на рівні висловлювань, іншими словами стосується лише оператора, який зараз працює. Allow_Snapshot_Isolation - це ізоляція на рівні транзакцій, все між початком транзакції та фіксацією. Вони можуть бути задіяні окремо, але встановлюється однаковий наклад 14 байтів на ряд.
Делюкс

дякую за додавання додаткових деталей щодо встановлення 14-байтних накладних витрат. Кім розповідає про це у відео, але дуже корисно мати це також у тексті.
Алі Разегі

15

Добре, повернувся додому і випробував. Ось спостереження.

CREATE DATABASE TEST;
GO
CREATE TABLE TABLE1
(
    ID tinyint,
    Details varchar(10)
);
GO
INSERT INTO TABLE1
VALUES (1, 'Original');
GO

SELECT
    name,
    snapshot_isolation_state_desc,
    is_read_committed_snapshot_on
FROM sys.databases
WHERE name = 'TEST';
GO

Перший тест з обома налаштуваннями підтверджено, що ВИМКНЕНО.

Запит 1

USE TEST;

BEGIN TRAN
UPDATE TABLE1
SET Details = 'Update'
WHERE ID = 1;

--COMMIT;
--ROLLBACK;
GO

Запит 2

USE TEST;

SELECT ID, Details
FROM TABLE1
WHERE ID = 1;
GO

У цьому тесті запит 2 чекає, коли запит 1 здійсниться, dm_tran_locks DMV показує, що ексклюзивний замок на TABLE1, здійснений запитом 1.

USE TEST;

SELECT
    DB_NAME(tl.resource_database_id) AS DBName,
    resource_type,
    OBJECT_NAME(resource_associated_entity_id) AS tbl_name,
    request_mode,
    request_status,
    request_session_id
FROM sys.dm_tran_locks tl
WHERE 
    resource_database_id = db_id('TEST')
    AND resource_type = 'OBJECT'

Другий тест , відкат попередньої транзакції, встановіть READ_COMMITTED_SNAPSHOT ON, але ALLOW_SNAPSHOT_ISOLATION вимкнено.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT ON
WITH ROLLBACK IMMEDIATE;
GO

Запустіть запит 1 та виконайте запит 2. DMV показує, що запит 1 містить ексклюзивний замок, але запит 2 повертає деталі з «Оригіналом», без запиту 1 здійснювати транзакцію. Здається, що версія READ_COMMITTED версій на місці є.

Додавання SET TRANSACTION ISOLATION LEVEL SNAPSHOT;запитів 1 і запиту 2 та запуску запиту 1 або запиту 2 повертає помилку - транзакція виділення знімка не вдалася отримати доступ до бази даних "TEST", оскільки ізоляція знімків не дозволена в цій базі даних. Використовуйте ALTER DATABASE, щоб дозволити ізоляцію знімків.

Третій тест , відкат попередньої транзакції. Увімкніть READ_COMMITTED_SNAPSHOT OFF та ALLOW_SNAPSHOT_ISOLATION ON.

ALTER DATABASE TEST
SET READ_COMMITTED_SNAPSHOT OFF
WITH ROLLBACK IMMEDIATE;
GO

ALTER DATABASE TEST
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

Запустіть запит 1, а потім запит 2. DMV показує ексклюзивний замок, який виникає за запитом 1. Схоже, що запит 2 чекає завершення запиту 1. Увімкнення ALLOW_SNAPSHOT_ISOLATION не відображається, щоб увімкнути ПРОЧИТАНО КОМИТИРОВАНО версію рядків.

Додавання SET TRANSACTION ISOLATION LEVEL SNAPSHOT;до запиту 1 та запиту 2. Запустіть запит 1, а потім запит 2. Поки DMV показує, що запит 1 містить ексклюзивний замок, запит 2 повертає деталі з "Оригінал". Здається, ізоляція знімків на місці.

Спостереження з тесту показує, що READ_COMMITTED_SNAPSHOTсаме воно вмикає / відключає версію рядків READ COMMITTED незалежно від ALLOW_SNAPSHOT_ISOLATIONналаштування, і навпаки.


4

Ваше розуміння правильне. Мені подобається коротке, чітке та просте визначення звідси :

Коли параметр бази даних READ_COMMITTED_SNAPSHOT увімкнено, транзакції, що встановлюють рівень дозволеного читання рівня ізоляції, використовують версію версій.

Коли параметр бази даних ALLOW_SNAPSHOT_ISOLATION увімкнено, транзакції можуть встановлювати рівень ізоляції знімків.

Схоже, багато непорозумінь походить від самої МС. Наприклад, тут кажуть:

Якщо встановити параметр бази даних READ_COMMITTED_SNAPSHOT значення УВІМКНЕНО, двигун бази даних використовує версію версій і ізоляцію знімків за замовчуванням, замість того, щоб використовувати блоки для захисту даних.

Але згадана "ізоляція знімків" не дорівнює поведінці транзакції, щодо якої set transaction isolation level snapshotзастосовується.

Що стосується різниці, гарне пояснення тут .

Напевно, було б краще, якби READ_COMMITTED_SNAPSHOT був названий як READ_COMMITTED_ROW_VERSIONING або щось подібне. :)


0

Мені подобається цей резюме від Microsoft :

Встановлення параметра READ_COMMITTED_SNAPSHOT ON дозволяє отримувати доступ до перетворених рядків під типовим рівнем ізоляції READ COMMITTED. Якщо для параметра READ_COMMITTED_SNAPSHOT встановлено значення OFF, потрібно чітко встановити рівень ізоляції знімка для кожного сеансу, щоб отримати доступ до рядків, що переглядаються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.