Транзакции между контейнерами

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

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

Любой интерпретируемый запрос, ссылающийся на таблицы, оптимизированные для памяти, считается частью межконтейнерной транзакции, выполняемой из явной или неявной транзакции или в режиме автоматической фиксации.

Изоляция отдельных операций

Каждая транзакция SQL Server имеет уровень изоляции. Уровень изоляции по умолчанию — Read Committed. Чтобы использовать другой уровень изоляции, можно задать уровень изоляции с помощью SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

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

Указание уровня изоляции отдельных операций

Чтобы задать другой уровень изоляции для набора инструкций в транзакции, можно использовать SET TRANSACTION ISOLATION LEVEL. В следующем примере транзакции используется уровень сериализуемой изоляции по умолчанию. Операции вставки и выбора в t3, t2 и t1 выполняются при повторяемой изоляции чтения.

set transaction isolation level serializable  
go  
  
begin transaction  
 ......  
  set transaction isolation level repeatable read  
  
  insert t3 select * from t1 join t2 on t1.id=t2.id  
  
  set transaction isolation level serializable  
 ......  
commit  

Чтобы задать уровень изоляции для отдельных операций чтения, который отличается от уровня изоляции по умолчанию в транзакции, можно использовать подсказку для таблицы (например, сериализуемость). Каждый выбор соответствует операции чтения и каждому обновлению и каждому удалению соответствует чтению, так как строка всегда должна быть прочитана, прежде чем она может быть обновлена или удалена. Операции вставки не имеют уровня изоляции, так как записи всегда изолированы в SQL Server. В следующем примере уровень изоляции по умолчанию для транзакции зафиксирован, но таблица t1 обращается к сериализуемой и t2 при изоляции моментальных снимков.

set transaction isolation level read committed  
go  
  
begin transaction  
 ......  
  
  insert t3 select * from t1 (serializable) join t2 (snapshot) on t1.id=t2.id  
  
  ......  
commit  

Семантика изоляции для отдельных операций

Сериализуемая транзакция T выполняется в полной изоляции. Это так, как если бы каждая другая транзакция была зафиксирована до начала T или запущена после фиксации T. Она становится более сложной, когда различные операции в транзакции имеют разные уровни изоляции.

Общая семантика уровней изоляции транзакций в SQL Server вместе с последствиями блокировки объясняется в разделе SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

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

Операция чтения данных возвращает ряд строк, удовлетворяющих условию фильтра.

Операции чтения выполняются в рамках транзакции T. Уровни изоляции для операций чтения можно понять с точки зрения,

Состояние коммита
Статус фиксации указывает, гарантировано ли, что чтение данных будет зафиксировано.

(Транзакционная) Согласованность
Транзакционная согласованность для набора операций чтения означает, что версии строк, которые считываются, гарантированно включают обновления из того же набора транзакций.

Система предоставляет транзакции T гарантии стабильности относительно прочитанных данных.
Стабильность указывает, повторяются ли операции чтения транзакции. То есть, если операции чтения повторятся, будут ли они возвращать одни и те же строки и версии строк?

Некоторые гарантии относятся к логическому времени окончания транзакции. Как правило, логическое время окончания — это время фиксации транзакции в базе данных. Если транзакция обращается к оптимизированным для памяти таблицам, то время логического окончания технически совпадает с началом этапа проверки. (Для получения дополнительной информации см. обсуждение времени существования транзакций в транзакциях в таблицах Memory-Optimized.)

Независимо от уровня изоляции транзакция (T) всегда видит свои собственные обновления:

Чтение непроверенных данных
Данные могут быть ни зафиксированы, ни согласованы, ни стабильны. Однако она будет включать более ранние операции записи, выполненные T.

READ COMMITTED (Уровень изоляции транзакций)
Прочитанные данные будут зафиксированы.

МОМЕНТАЛЬНЫЙ СНИМОК
Все операции чтения, выполняемые T при изоляции моментального снимка, имеют одинаковое логическое время чтения, которое является началом транзакции. Данные, которые были прочитаны, гарантированно зафиксированы и согласованы в момент логического чтения данных. Повторение чтения по состоянию на исходное время чтения гарантированно возвращает тот же результат.

ПОВТОРЯЕМОЕ ЧТЕНИЕ
Чтение данных гарантированно будет зафиксировано и стабильно до логического окончания транзакции.

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

Рассмотрим следующую транзакцию.

set transaction isolation level read committed  
go  
  
begin transaction  
  -- remove all rows from t3; the related read operation is performed under read committed   
  -- isolation, as this is the default for the transaction  
  delete from t3  
  
  -- copy the contents from t1 to t3; the read on t1 is performed under the serializable   
  -- isolation level  
  insert t3 select * from t1 (serializable)  
  
  -- compare t3 and t1; note: the result set may not be empty, as rows may have been added   
  -- by other transaction before this select, due to the read committed isolation level  
  select * from t3 except t1  
  
  -- compare t1 and t3; note: the result set is empty, as no rows have been added to t1   
  -- since its contents were copied to t1, due to the serializable isolation level  
  select * from t1 except t3  
commit  

Эта транзакция удаляет все строки из t3 на уровне изоляции Read Committed, копирует все строки из t1 в t3 под сериализуемой изоляцией, а затем сравнивает t1 и t3. Некоторые строки [не в t1] могли быть добавлены в t3 после того, как таблица была очищена. Строки не были добавлены в t1, так как копия была сериализуемой.

Хотя чтение из t1 в конце транзакции синтаксически считывается, оно эффективно сериализуется, так как то же чтение было выполнено ранее в транзакции под сериализуемой изоляцией: сериализуемость гарантирует, что если чтение выполняется в любой последующей точке транзакции, возвращаются те же строки.

Межконтейнерные транзакции и уровни изоляции

Межконтейнерная транзакция представляется как состоящая из двух сторон: дисковой стороны (для операций с таблицами на основе диска) и памяти оптимизированной стороны (для операций с оптимизированными для памяти таблицами). Эти две стороны могут иметь разные уровни изоляции. На самом деле отдельные операции чтения на каждой стороне могут иметь разные уровни изоляции.

Дисковая сторона заданной транзакции T достигает определенного уровня изоляции X, если выполняется одно из следующих условий:

  • Сеанс начинается в X. То есть, сеанс по умолчанию был X, либо потому что вы выполнили SET TRANSACTION ISOLATION LEVEL, либо это значение по умолчанию SQL Server.

  • Во время транзакции уровень изоляции по умолчанию изменяется на X с помощью SET TRANSACTION ISOLATION LEVEL.

  • Операция чтения в таблице на диске выполняется на уровне изоляции X с помощью синтаксиса WITH (X).

Оптимизированная для памяти сторона T достигает уровня изоляции Y, если во время выполнения T любая операция чтения в оптимизированной для памяти таблице или любая скомпилированная в собственном коде хранимая процедура выполняется на уровне изоляции Y.

Рассмотрим следующую транзакцию как пример. Здесь t1 и t2 — это таблицы на основе дисков, а t3 и t4 — это оптимизированные для памяти таблицы.

Сторона транзакции, использующая диск, достигает уровня изоляции "read committed", потому что она начинается именно на этом уровне. Сторона, основанная на диске, достигает повторяемого чтения, поскольку первая операция чтения также выполняется на этом уровне изоляции. Удаление в конце транзакции выполняется при уровне изоляции с подтверждением чтения, поэтому не вводит новый уровень изоляции.

Оптимизированная для памяти сторона транзакции может достичь одного из двух уровней: если условие1 истинно, оно достигает уровня сериализации, тогда как если оно ложно, оптимизированная для памяти сторона достигает только уровня изоляции снимков.

set transaction isolation level read committed  
go  
  
begin transaction  
  select * from t1 (repeatableread)  
  
  if condition1 begin  
    insert t3 select * from t4 (serializable)  
  end  
  else begin  
    insert t3 select * from t4 (snapshot)  
  end  
  
  delete from t1  
commit  

Поддерживаемые уровни изоляции для межконтейнерных транзакций

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

Оптимизированные для памяти таблицы поддерживают уровни изоляции SNAPSHOT, REPEATABLE READ и SERIALIZABLE. Для транзакций автоматической фиксации таблицы, оптимизированные для памяти, поддерживают уровень изоляции READ COMMITTED.

Поддерживаются следующие сценарии:

  • READ UNCOMMITTED, READ COMMITTED и READ_COMMITTED_SNAPSHOT межконтейнерные транзакции могут получить доступ к оптимизированным для памяти таблицам в разделе SNAPSHOT, REPEATABLE READ и SERIALIZABLE изоляции. Гарантия READ COMMITTED сохраняется для транзакции; все строки, прочитанные транзакцией, были зафиксированы в базе данных.

  • Повторяемые транзакции READ и SERIALIZABLE могут получить доступ к оптимизированным для памяти таблицам в изоляции SNAPSHOT.

Транзакции только для чтения в межконтейнерной среде

Большинство транзакций только для чтения в SQL Server откатываются при попытке фиксации. Так как в базе данных нет изменений, система просто освобождает ресурсы, используемые транзакцией. Для транзакций на основе диска только для чтения все блокировки, сделанные транзакцией, освобождаются. Для транзакций, оптимизированных только для чтения и использующих нативно скомпилированную процедуру, проверка не выполняется.

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

Явные или неявные межконтейнерные транзакции с доступом только для чтения выполняют валидацию при фиксации, если транзакция обращается к таблицам, оптимизированным для памяти, при уровне изоляции REPEATABLE READ или SERIALIZABLE. Дополнительные сведения о проверке см. в разделе об обнаружении конфликтов, проверке и фиксации проверок зависимостей в транзакциях в таблицах Memory-Optimized.

См. также

Общие сведения о транзакциях в таблицах Memory-Optimized
Рекомендации по уровням изоляции транзакций с таблицами Memory-Optimized
Рекомендации по логике повторных попыток для транзакций в таблицах Memory-Optimized