Атомарные блоки в собственных процедурах
Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure
BEGIN ATOMIC — часть стандарта ANSI SQL. SQL Server поддерживает атомарные блоки на верхнем уровне скомпилированных хранимых процедур, а также для скомпилированных в собственном коде скалярных пользовательских функций. Дополнительные сведения об этих функциях см. в разделе Скалярные определяемые пользователем функции для выполняющейся в памяти OLTP.
Каждая скомпилированная в собственном коде хранимая процедура содержит ровно один блок инструкций Transact-SQL. Это блок ATOMIC.
Не собственные, интерпретированные хранимые процедуры Transact-SQL и нерегламентированные пакеты не поддерживают атомарные блоки.
Блоки ATOMIC выполняются (атомарным образом) в рамках транзакции. Либо все инструкции в блоке выполняются успешно, либо весь блок будет подвергнут откату до точки сохранения, созданной в начале блока. Кроме того, параметры сеанса фиксируются для блока ATOMIC. Выполнение того же блока ATOMIC в сеансах с различными параметрами приведет к тому же поведению независимо от параметров текущего сеанса.
Транзакции и обработка ошибок
Если транзакция уже существует в сеансе (поскольку пакет выполнил инструкцию BEGIN TRANSACTION и транзакция остается активной), то при запуске блока ATOMIC создается точка сохранения в транзакции. Если блок выходит без исключения, точка сохранения, которая была создана для блока, фиксируется, но транзакция не будет фиксироваться до тех пор, пока не будет зафиксирована транзакция на уровне сеанса. Если блок вызывает исключение, то результаты блока подвергаются откату, но транзакция на уровне сеанса продолжается, если исключение не приводит к ошибке транзакции. Например, конфликт записи приводит к ошибке транзакции, но не к ошибке приведения типов.
Если отсутствуют активные транзакции в сеансе, то BEGIN ATOMIC запускает новую транзакцию. Если вне блока не возникло исключение, то транзакция будет зафиксирована в конце блока. Если блок вызывает исключение (то есть исключение не обрабатывается и не перехватывается внутри блока), то будет произведен откат этой транзакции. Для транзакций, которые охватывают один блок ATOMIC (одна хранимая процедура, скомпилированная в собственном коде), нет необходимости записывать явные инструкции BEGIN TRANSACTION и COMMIT или ROLLBACK .
Все хранимые процедуры, скомпилированные в собственном коде, поддерживают конструкции TRY, CATCHи THROW для обработки ошибок. ФункцияRAISERROR не поддерживается.
Следующий пример иллюстрирует работу функции обработки ошибок с блоками ATOMIC и хранимыми процедурами, скомпилированными в собственном коде:
-- sample table
CREATE TABLE dbo.t1 (
c1 int not null primary key nonclustered
)
WITH (MEMORY_OPTIMIZED=ON)
GO
-- sample proc that inserts 2 rows
CREATE PROCEDURE dbo.usp_t1 @v1 bigint not null, @v2 bigint not null
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english', DELAYED_DURABILITY = ON)
INSERT dbo.t1 VALUES (@v1)
INSERT dbo.t1 VALUES (@v2)
END
GO
-- insert two rows
EXEC dbo.usp_t1 1, 2
GO
-- verify we have no active transaction
SELECT @@TRANCOUNT
GO
-- verify the rows 1 and 2 were committed
SELECT c1 FROM dbo.t1
GO
-- execute proc with arithmetic overflow
EXEC dbo.usp_t1 3, 4444444444444
GO
-- expected error message:
-- Msg 8115, Level 16, State 0, Procedure usp_t1
-- Arithmetic overflow error converting bigint to data type int.
-- verify we have no active transaction
SELECT @@TRANCOUNT
GO
-- verify rows 3 was not committed; usp_t1 has been rolled back
SELECT c1 FROM dbo.t1
GO
-- start a new transaction
BEGIN TRANSACTION
-- insert rows 3 and 4
EXEC dbo.usp_t1 3, 4
-- verify there is still an active transaction
SELECT @@TRANCOUNT
-- verify the rows 3 and 4 were inserted
SELECT c1 FROM dbo.t1 WITH (SNAPSHOT)
ORDER BY c1
-- catch the arithmetic overflow error
BEGIN TRY
EXEC dbo.usp_t1 5, 4444444444444
END TRY
BEGIN CATCH
PRINT N'Error occurred: ' + error_message()
END CATCH
-- verify there is still an active transaction
SELECT @@TRANCOUNT
-- verify rows 3 and 4 are still in the table, and row 5 has not been inserted
SELECT c1 FROM dbo.t1 WITH (SNAPSHOT)
ORDER BY c1
COMMIT
GO
-- verify we have no active transaction
SELECT @@TRANCOUNT
GO
-- verify rows 3 and 4 has been committed
SELECT c1 FROM dbo.t1
ORDER BY c1
GO
Следующие сообщения об ошибке, относящиеся к таблицам с оптимизацией для памяти, указывают на неудачу транзакции. Если они встречаются в атомарном блоке, это приведет к тому, что транзакция будет прервана: 10772, 41301, 41302, 41305, 41325, 41332, 41333 и 41839.
Параметры сеанса
Параметры сеанса в блоках ATOMIC фиксируются, если выполнена компиляция хранимой процедуры. Некоторые параметры могут быть заданы с помощью BEGIN ATOMIC , тогда как другие параметры всегда фиксируются в одно и то же значение.
Требуются следующие параметры с BEGIN ATOMIC.
Обязательный параметр | Description |
---|---|
TRANSACTION ISOLATION LEVEL | Поддерживаются значения SNAPSHOT, REPEATABLEREADи SERIALIZABLE. |
LANGUAGE | Определяет форматы даты и времени и системных сообщений. Поддерживаются все языки и псевдонимы в sys.syslanguages (Transact-SQL ). |
Следующие параметры являются необязательными.
Необязательный параметр | Description |
---|---|
DATEFORMAT | Поддерживаются все форматы дат SQL Server. Если он указан, параметр DATEFORMAT переопределяет формат даты по умолчанию, связанный с объектом LANGUAGE. |
DATEFIRST | Если он указан, параметр DATEFIRST переопределяет значение по умолчанию, связанное с LANGUAGE. |
DELAYED_DURABILITY | Поддерживаются значения OFF и ON. Фиксации транзакций SQL Server могут быть полностью устойчивыми, стандартными или отложенными устойчивыми. Дополнительные сведения см. в разделе "Устойчивость транзакций управления". |
Следующие параметры SET имеют одно и то же значение по умолчанию для всех блоков ATOMIC во всех хранимых процедурах, скомпилированных в собственном коде.
Установленный параметр | Системные значения по умолчанию для блоков ATOMIC |
---|---|
ANSI_NULLS | DNS |
ANSI_PADDING | DNS |
ANSI_WARNING | DNS |
ARITHABORT | DNS |
ARITHIGNORE | ВЫКЛ. |
CONCAT_NULL_YIELDS_NULL | DNS |
IDENTITY_INSERT | ВЫКЛ. |
NOCOUNT | DNS |
NUMERIC_ROUNDABORT | ВЫКЛ. |
QUOTED_IDENTIFIER | DNS |
ROWCOUNT | 0 |
TEXTSIZE | 0 |
XACT_ABORT | ВЫКЛ. Неперехваченные исключения приводят к откату блока ATOMIC, но не вызывают прерывание транзакции, если ошибка не критична для транзакции. |