it-roy-ru.com

Чтение зафиксированного снимка и уровня изоляции снимка

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

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

Спасибо

63
user173552

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

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

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

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

70
Bill Paetzke

 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

26
Akira Yamamoto

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

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

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

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

3
user3444696

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

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

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

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

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

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

  • Разрешить клиенту запрашивать SNAPSHOT для операторов SQL (транзакций).
  • Код должен запрашивать снимки «транзакции» (например, SET TRANSACTION ...)
  • ALTER DATABASE 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 блокировки строк реализованы с использованием блокировок на уровне блоков (блокировка случайных строк, связанных с близостью хранилища), и что существует порог, когда множественные блокировки запускают блокировку таблицы - предположительно, более «оптимистичная» оптимизация производительности с риском блокирования проблем в загруженных базах данных.

0
Cris Mooney