Поделиться через


Транзакции в таблицах Memory-Optimized

Управление версиями строк для таблиц на диске (с использованием изоляции снимков или READ_COMMITTED_SNAPSHOT) обеспечивает форму управления оптимистичной конкурентностью. Читатели и писатели не блокируют друг друга. При использовании оптимизированных для памяти таблиц записи не блокируют друг друга. При версионировании строк на дисковых таблицах одна транзакция блокирует строку, и одновременные транзакции, пытающиеся обновить строку, блокируются. Оптимизированные для памяти таблицы не требуют блокировки. Вместо этого, если две транзакции пытаются обновить одну и ту же строку, возникнет конфликт записи и записи (ошибка 41302).

Оптимизированные для памяти таблицы, в отличие от таблиц на основе дисков, позволяют управление оптимистической параллелизацией на более высоких уровнях изоляции, таких как REPEATABLE READ и SERIALIZABLE. Блокировки не используются для обеспечения уровней изоляции. Вместо этого в конце проверки транзакции гарантируется повторяющееся предположение о читаемости или сериализации. Если допущения нарушаются, транзакция завершается. Дополнительные сведения см. в разделе "Уровни изоляции транзакций".

Важные семантики транзакций для оптимизированных для памяти таблиц:

  • Многоверсийность

  • Изоляция транзакций на основе моментальных снимков

  • Оптимистичный

  • Обнаружение конфликтов

Каждая из этих семантик описана в следующих разделах.

Многоверсионность в таблицах Memory-Optimized

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

Данные таблицы, оптимизированные для памяти, основаны на версиях. Для любой строки могут быть разные версии строк, допустимые в разные моменты времени. Таблицы на основе дисков поддерживают разные версии строк, если READ_COMMITTED_SNAPSHOT или ALLOW_SNAPSHOT_ISOLATION включены. Таблицы, оптимизированные для памяти, поддерживают разные версии строк, даже при отключенных READ_COMMITTED_SNAPSHOT и ALLOW_SNAPSHOT_ISOLATION. Версии строк оптимизированных для памяти таблиц не поддерживаются в tempdb. Вместо этого версии строк сохраняются в строке как часть структур данных, оптимизированных для памяти, сохраняющих строки в памяти.

изоляция транзакций Snapshot-Based для таблиц Memory-Optimized

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

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

Управление оптимистичным параллелизмом для таблиц Memory-Optimized

Конфликты и сбои случаются редко, и транзакции в таблицах с оптимизацией под память предполагают отсутствие конфликтов с параллельными транзакциями, что обеспечивает успешное выполнение операций. Транзакции не используют блокировки или защёлки в таблицах, оптимизированных для памяти, чтобы гарантировать изоляцию транзакций. Писатели не блокируют читателей. Писатели не мешают писателям. Вместо этого транзакции продолжаются в соответствии с (оптимистическим) предположением, что не будет конфликтов с другими транзакциями. Не использование блокировок и засовов и не ожидание завершения обработки одних и тех же строк улучшает производительность.

Кроме того, если транзакция (TxA) считывает строки, которые были вставлены или изменены другой транзакцией (TxB), находящейся в процессе фиксации, она оптимистично предполагает, что другая транзакция будет зафиксирована, вместо ожидания завершения фиксации. В этом случае транзакция TxA будет иметь зависимость фиксации от транзакции TxB.

Обнаружение конфликтов, проверка и фиксация проверок зависимостей

SQL Server обнаруживает конфликты между параллельными транзакциями, а также нарушениями уровня изоляции и приведет к возникновению одной из конфликтующих транзакций. Эта транзакция должна быть повторно выполнена. (Дополнительные сведения см. в руководстве по логике повторных попыток для транзакций в таблицах Memory-Optimized.)

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

При обнаружении конфликта транзакция завершается, и клиенту необходимо повторить попытку.

В следующей таблице приведены условия ошибки для транзакций, обращаюющихся к таблицам, оптимизированным для памяти.

Условия ошибки для транзакций, обращаюющихся к таблицам, оптимизированным для памяти.

Ошибка Сценарий
Конфликт при записи. Попытка обновить запись, обновленную с момента начала транзакции. Строка, которую нужно обновить или удалить, может быть обновлена или удалена параллельной транзакцией.
Повторяющийся сбой проверки чтения. Строка, считываемая транзакцией, изменилась (обновлена или удалена) с момента начала транзакции. Повторяемая проверка чтения обычно происходит при использовании уровней изоляции транзакций REPEATABLE READ и SERIALIZABLE.
Сбой сериализуемой проверки. Новая (фантомная) строка была вставлена в один из диапазонов сканирования в транзакции с момента начала транзакции. Строка была бы видна для транзакции, если строка была зафиксирована в базе данных до начала транзакции. Валидация на уровне SERIALIZABLE обычно происходит при использовании изоляции SERIALIZABLE и проверке ограничений первичного ключа.
Сбой фиксации зависимостей. Транзакция зависела от другой транзакции, которую не удалось зафиксировать, либо из-за одного из сбоев, перечисленных в этой таблице, либо из-за недостатка памяти, либо из-за сбоя фиксации в журнале транзакций. Этот сбой может возникать как с транзакциями для чтения и записи, так и с транзакциями только для чтения.

Время существования транзакции

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

Время существования транзакции. Время существования транзакции, которая обращается к таблицам, оптимизированным для памяти.

Обычная обработка

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

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

Если операция обновления или удаления отображает, что строка была обновлена или удалена с логического запуска транзакции, операция завершится ошибкой 41302. Сообщение об ошибке 41302 — "Текущая транзакция пыталась обновить запись в таблице X, которая была обновлена с момента запуска этой транзакции. Транзакция была прервана".

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

Фиксация зависимостей

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

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

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

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

Если любая из зависимых транзакций не зафиксируется, происходит сбой зависимости фиксации. Это означает, что транзакция не будет зафиксирована с ошибкой 41301 ("Предыдущая транзакция, от которой зависела текущая транзакция, была прервана, и текущая транзакция больше не может быть подтверждена.").

Этап проверки

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

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

Повторяемая проверка чтения

Если уровень изоляции транзакции — REPEATABLE READ или SERIALIZABLE, или таблицы доступны в изоляции REPEATABLE READ или SERIALIZABLE (дополнительные сведения см. в разделе об изоляции отдельных операций в уровнях изоляции транзакций), система проверяет, что операции чтения повторяются. Это означает, что версии строк, считываемых транзакцией, по-прежнему являются допустимыми версиями строк во время логического окончания транзакции.

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

Эта ошибка также может возникать, если таблица удаляется после операции вставки, обновления или удаления, а также перед фиксацией транзакции. Это применяется только к операциям вставки, обновления или удаления в нативно скомпилированных хранимых процедурах. Такие операции записи, выполняемые с помощью интерпретированных Transact-SQL приводят к блокировке и ожиданию фиксации транзакции инструкцией DROP TABLE.

Сериализуемая проверка

Сериализуемая проверка выполняется в двух случаях:

  • Если уровень изоляции транзакции равен SERIALIZABLE или таблицы используются с изоляцией SERIALIZABLE.

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

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

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

Если обнаружены фантомные строки, транзакция не зафиксируется с ошибкой 41325 ("Текущая транзакция не удалось зафиксировать из-за сбоя сериализуемой проверки".

Обработка фиксации

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

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

Ограничения

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

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

  • Оптимизированные для памяти таблицы не поддерживают блокировку. Явные блокировки с помощью подсказок блокировки (например, TABLOCK, XLOCK, ROWLOCK) не поддерживаются в таблицах, оптимизированных для памяти.

См. также

Общие сведения о транзакциях в таблицах Memory-Optimized