Изоляция моментального снимка oltp-транзакции SQL Server в памяти

#sql-server #sql-server-2016 #memory-optimized-tables #snapshot-isolation #in-memory-oltp

#sql-сервер #sql-server-2016 #оптимизированные для памяти таблицы #моментальный снимок -изоляция #в памяти-oltp

Вопрос:

Пытаюсь понять, как работают уровни изоляции транзакций в таблицах, оптимизированных для памяти SQL Server (oltp в памяти).

Если я выполню следующий запрос:

 SET TRANSACTION ISOLATION LEVEL READ COMMITTED

BEGIN TRANSACTION

SELECT *
FROM tm.Tasks
  

Отображается сообщение об ошибке:

Доступ к таблицам, оптимизированным для памяти, с использованием уровня изоляции с фиксацией ЧТЕНИЯ, поддерживается только для транзакций с автоматической фиксацией. Это не поддерживается для явных или неявных транзакций. Укажите поддерживаемый уровень изоляции для таблицы, оптимизированной для памяти, используя подсказку таблицы, например, с помощью (SNAPSHOT).

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

 SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO

BEGIN TRANSACTION

SELECT *
FROM tm.Tasks WITH(SNAPSHOT)
  

Но если я изменю уровень изоляции транзакции через SET TRANSACTION ISOLATION LEVEL SNAPSHOT и удалю подсказку таблицы:

 SET TRANSACTION ISOLATION LEVEL SNAPSHOT

BEGIN TRANSACTION

SELECT *
FROM tm.Tasks
  

он снова не работает, отображая сообщение об ошибке:

К таблицам, оптимизированным для памяти, и изначально скомпилированным модулям невозможно получить доступ или создать, если для УРОВНЯ ИЗОЛЯЦИИ ТРАНЗАКЦИИ сеанса установлено значение SNAPSHOT.

Почему это работает с подсказкой таблицы и установкой уровня изоляции транзакции через

 SET TRANSACTION ISOLATION LEVEL SNAPSHOT
  

не работает?

Обновление: попытался установить MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT значение ON , по-прежнему получая ту же ошибку из последнего запроса:

К таблицам, оптимизированным для памяти, и изначально скомпилированным модулям невозможно получить доступ или создать, если для УРОВНЯ ИЗОЛЯЦИИ ТРАНЗАКЦИИ сеанса установлено значение SNAPSHOT.

Комментарии:

1. Вам нужно использовать MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT в дополнение к тому, чтобы не использовать SET TRANSACTION ISOLATION LEVEL SNAPSHOT явно. Другими словами, используйте SET TRANSACTION ISOLATION LEVEL READ COMMITTED в сочетании с этим параметром (и / или READ_COMMITTED_SNAPSHOT , если вы хотите то же самое для объектов на диске). По общему признанию, это немного сбивает с толку, но имеет немного больше смысла, когда у вас есть транзакции как с объектами на диске, так и с объектами в памяти.

2. @JeroenMostert Насколько я знаю, READ_COMMITTED_SNAPSHOT (пессимистические записи) — это не то же самое, что SNAPSHOT (оптимистичные записи). Итак, если мне нужна транзакция с задействованными таблицами, оптимизированными как для диска, так и для памяти, невозможно ли использовать уровень изоляции моментального снимка?

3. READ_COMMITTED_SNAPSHOT означает не более и не менее того, что READ COMMITTED обрабатывается так, как если бы это было SNAPSHOT . Нет разницы в терминах оптимизма или пессимизма; изоляция моментальных снимков всегда оптимистична, поскольку запись завершится ошибкой, если данные были изменены с момента запуска транзакции. Если вам нужна READ COMMITTED семантика на основе блокировок («пессимистичная») с фактической изоляцией моментальных снимков, вы можете использовать READCOMMITTEDLOCK подсказку таблицы. Явные транзакции, в которых вы объединяете таблицы памяти и диска, немного сложны, но они не должны быть очень распространенными.

Ответ №1:

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

Все это подробно описано в моих сообщениях:

http://nedotter.com/archive/2017/08/all-about-in-memory-isolation-levels-part-1/
http://nedotter.com/archive/2017/08/all-about-in-memory-isolation-levels-part-2/

Пожалуйста, дайте мне знать, если у вас возникнут дополнительные вопросы по этой часто неправильно понимаемой теме.

Ответ №2:

MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT Параметр базы данных должен быть включен, чтобы использовать явную SNAPSHOT транзакцию без подсказок. Ниже приводится выдержка из документации (выделено мной):

Явный — ваш Transact-SQL содержит код ЗАПУСКА ТРАНЗАКЦИИ вместе с возможной транзакцией ФИКСАЦИИ. В одну транзакцию могут быть включены два или более операторов. В явном режиме необходимо либо использовать параметр базы данных MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT, либо закодировать табличную подсказку об уровне изоляции транзакции в таблице, оптимизированной для памяти, в предложении FROM.

Ниже приведен пример, показывающий, как включить этот параметр базы данных:

 ALTER DATABASE YourDatabase
    SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = ON;