#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;