Чтение зафиксированного снимка и уровня изоляции снимка - PullRequest
67 голосов
/ 30 апреля 2010

Может ли кто-нибудь помочь мне понять, когда использовать уровень изоляции SNAPSHOT над READ COMMITTED SNAPSHOT в SQL Server?

Я понимаю, что в большинстве случаев READ COMMITTED SNAPSHOT работает, но не уверен, когда пойдет для изоляции SNAPSHOT.

Спасибо

Ответы [ 4 ]

71 голосов
/ 06 мая 2010

READ COMMITTED SNAPSHOT делает оптимистичные чтения и пессимистичные записи.Напротив, SNAPSHOT делает оптимистичные чтения и оптимистичные записи.

Microsoft рекомендует READ COMMITTED SNAPSHOT для большинства приложений, которым требуется версионирование строк.

Прочитайте эту превосходную статью Microsoft: Выбор версионирования строкуровни изоляции .Это объясняет преимущества и затраты обоих уровней изоляции.

А вот более тщательный: http://msdn.microsoft.com/en-us/library/ms345124(SQL.90).aspx

31 голосов
/ 30 марта 2016

enter image description here [! [Таблица уровней изоляции] [2]] [2]

См. Пример ниже:

Считать зафиксированный снимок

Измените свойство базы данных, как показано ниже

ALTER DATABASE SQLAuthority
SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE
GO

Сессия 1

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 4
WHERE i = 1

Сессия 2

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1

Результат - Запрос в сеансе 2 показывает старое значение (1, ОДИН), поскольку текущая транзакция НЕ зафиксирована. Это способ избежать блокировки и чтения зафиксированных данных.

Сессия 1

COMMIT

Сессия 2

USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1

Результат - запрос в сеансе 2 не показывает строк, потому что строка обновляется в сеансе 1. Итак, мы снова видим зафиксированные данные.

Уровень изоляции моментального снимка

Это новый уровень изоляции, который был доступен начиная с SQL Server 2005 и далее. Для этой функции необходимо внести изменения в приложение, поскольку оно должно использовать новый уровень изоляции.

Измените настройки базы данных, используя ниже. Нам нужно убедиться, что в базе данных нет транзакций.

ALTER DATABASE SQLAuthority SET AllOW_SNAPSHOT_ISOLATION ON

Теперь нам также нужно изменить уровень изоляции соединения, используя ниже

Сессия 1

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 10
WHERE i = 2

Сессия 2

SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2

Результат: даже если мы изменили значение на 10, мы все равно увидим старую запись в сеансе 2 (2, ДВА).

Теперь давайте сделаем транзакцию в сеансе 1

Сессия 1

COMMIT

Давайте вернемся к сеансу 2 и снова запустим select.

Сессия 2

SELECT *
FROM   DemoTable
WHERE i = 2

Мы все равно увидим запись, потому что в сеансе 2 была указана транзакция с изоляцией моментального снимка. Если мы не завершим транзакцию, мы не увидим последнюю запись.

Сессия 2

COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2

Теперь мы не должны видеть строку, так как она уже обновлена.

См .: SQL Authority , Safari Books Online

4 голосов
/ 26 января 2018

Сравнение Snapshot и Snapshot Read Committed не обходится без обсуждения страшного исключения «конфликт обновления снимка», которое может произойти в Snapshot, но не Snapshot Read Committed.

В двух словах, изоляция моментальных снимков получает моментальный снимок зафиксированных данных при начале транзакции , а затем использует оптимистическую блокировку как для чтения, так и для записи. Если при попытке зафиксировать транзакцию оказывается, что что-то еще изменило некоторые из этих же данных, база данных откатит всю транзакцию и выдаст ошибку, вызывающую исключение конфликта обновления моментального снимка в вызывающем коде. Это связано с тем, что версия данных, затронутых транзакцией, в конце транзакции отличается от версии в начале транзакции.

Snapshot Read Committed не страдает от этой проблемы, поскольку использует блокировку при записи (пессимистичные записи) и получает информацию о версии моментального снимка всех зафиксированных данных при статистике каждого оператора .

Возможность конфликтов обновления снимка, происходящих в Snapshot и NOT Snapshot Read Committed, является чрезвычайно существенной разницей между ними.

0 голосов
/ 15 июля 2016

Все еще актуально, начиная с комментариев Билла, я прочитал больше и сделал заметки, которые могут быть полезны для кого-то еще.

По умолчанию отдельные операторы (включая «SELECT») работают с «зафиксированными» данными (READ COMMITTED), возникает вопрос: ждут ли они «простоя» данных и не дают другим работать при чтении?

Настройка через правый клик БД «Свойства -> Параметры -> Разное»:

Параллелизм / блокировка: снимок с фиксацией считывания включен [по умолчанию выключен, должен быть включен]:

  • Используйте SNAPSHOT для выбора (чтения), не ждите других и не блокируйте их.
  • Работа с эффектами без изменения кода
  • ALTER DATABASE SET READ_COMMITTED_SNAPSHOT [ON | OFF]
  • ВЫБРАТЬ имя, is_read_committed_snapshot_on FROM sys.databases

Консистенция: Разрешить Snapshot Isolation [по умолчанию выключен, спорно - OK OFF]:

  • Разрешить клиенту запрашивать SNAPSHOT для операторов SQL (транзакций).
  • Код должен запрашивать снимки «транзакции» (например, SET TRANSACTION ...)
  • ALTER DATABASE SET SET ALLOW_SNAPSHOT_ISOLATION [ON | OFF]
  • ВЫБРАТЬ имя, is_read_committed_snapshot_on FROM sys.databases

На вопрос: это не один или другой между Read Committed Snapshot и Allow Snapshot Isolation. Это два случая снэпшота, которые могут быть включены или выключены независимо, а Allow Snapshot Isolation - немного более сложная тема. Разрешить изоляцию моментальных снимков позволяет коду продвинуться дальше, управляя землей моментальных снимков.

Проблема кажется ясной, если подумать об одной строке: по умолчанию система не имеет копии, поэтому читатель должен ждать, если кто-то еще пишет, и писатель также должен ждать, если кто-то еще читает - строка должна заблокировать все время. Включение «Read Read Committed Snapshot On» активирует базу данных для поддержки «копий снимков», чтобы избежать этих блокировок.

Рамблинг на ...

По моему мнению, «Read Read Committed Snapshot On» должен быть «TRUE» для любых обычных баз данных MS SQLServer, и это преждевременная оптимизация, поскольку по умолчанию он выдает «FALSE».

Однако мне сказали, что блокировка одной строки ухудшается не только потому, что вы можете обращаться к нескольким строкам в разных таблицах, но и потому, что в SQL Server блокировки строк реализованы с использованием блокировок на уровне блоков (блокировка случайных строк, связанных с близостью хранилища) ) и что существует пороговое значение, при котором множественные блокировки запускают блокировку таблицы - предположительно, более «оптимистичная» оптимизация производительности с риском блокирования проблем в загруженных базах данных.

...