Использование транзакций в пуле SQL в Azure Synapse
Эта статья содержит советы по реализации транзакций и разработке решений в пуле SQL.
Основные принципы
Как и следовало ожидать, пул SQL поддерживает транзакции как часть рабочей нагрузки хранилища данных. Однако в целях обеспечения производительности пула SQL в большом масштабе некоторые возможности ограничиваются по сравнению с SQL Server. В этой статье описываются отличия.
Уровни изоляции транзакций
Пул SQL реализует транзакции ACID. Уровень изоляции транзакционной поддержки по умолчанию — READ UNCOMMITTED. Его можно заменить уровнем READ COMMITTED SNAPSHOT ISOLATION, включив параметр базы данных READ_COMMITTED_SNAPSHOT для пользовательского пула SQL при подключении к базе данных master.
После его включения все транзакции в этой базе данных выполняются в режиме READ COMMITTED SNAPSHOT ISOLATION, и параметр READ UNCOMMITTED на уровне сеанса учитываться не будет. Дополнительные сведения см. в разделе Параметры ALTER DATABASE SET (Transact-SQL).
Размер транзакции
Размер одной транзакции, изменяющей данные, ограничен. Действует ограничение по распределению. Следовательно, можно вычислить общие выделенные ресурсы, перемножив величины ограничения и распределения.
Чтобы приблизительно определить максимальное количество строк в транзакции, разделите величину ограничения распределения на значение общего размера каждой строки. Для столбцов переменной длины рекомендуется брать среднюю длину столбца, а не максимальный размер.
В следующей таблице было сделано два предположения:
- выполнено равномерное распределение данных;
- средняя длина строки составляет 250 байтов.
Поколение 2
DWU | Ограничение распределения (ГБ) | Число распределений | Максимальный размер транзакции (ГБ) | # Число строк в распределении | Максимальное число строк на транзакцию |
---|---|---|---|---|---|
DW100c | 1 | 60 | 60 | 4 000 000 | 240 000 000 |
DW200c | 1.5 | 60 | 90 | 6 000 000 | 360 000 000 |
DW300c | 2.25 | 60 | 135 | 9 000 000 | 540 000 000 |
DW400c | 3 | 60 | 180 | 12 000 000 | 720 000 000 |
DW500c | 3,75 | 60 | 225 | 15 000 000 | 900 000 000 |
DW1000c | 7.5 | 60 | 450 | 30 000 000 | 1 800 000 000 |
DW1500c | 11,25 | 60 | 675 | 45 000 000 | 2 700 000 000 |
DW2000c | 15 | 60 | 900 | 60 000 000 | 3 600 000 000 |
DW2500c | 18,75 | 60 | 1125 | 75 000 000 | 4 500 000 000 |
DW3000c | 22,5 | 60 | 1350 | 90 000 000 | 5 400 000 000 |
DW5000c | 37,5 | 60 | 2,250 | 150 000 000 | 9 000 000 000 |
DW6000c | 45 | 60 | 2700 | 180 000 000 | 10 800 000 000 |
DW7500c | 56,25 | 60 | 3,375 | 225 000 000 | 13 500 000 000 |
DW10000c | 75 | 60 | 4 500 | 300 000 000 | 18 000 000 000 |
DW15000c | 112,5 | 60 | 6750 | 450 000 000 | 27 000 000 000 |
DW30000c | 225 | 60 | 13 500 | 900 000 000 | 54 000 000 000 |
Поколение 1
DWU | Ограничение распределения (ГБ) | Число распределений | Максимальный размер транзакции (ГБ) | # Число строк в распределении | Максимальное число строк на транзакцию |
---|---|---|---|---|---|
DW100 | 1 | 60 | 60 | 4 000 000 | 240 000 000 |
DW200 | 1.5 | 60 | 90 | 6 000 000 | 360 000 000 |
DW300 | 2.25 | 60 | 135 | 9 000 000 | 540 000 000 |
DW400 | 3 | 60 | 180 | 12 000 000 | 720 000 000 |
DW500 | 3,75 | 60 | 225 | 15 000 000 | 900 000 000 |
DW600 | 4.5. | 60 | 270 | 18 000 000 | 1 080 000 000 |
DW1000 | 7.5 | 60 | 450 | 30 000 000 | 1 800 000 000 |
DW1200 | 9 | 60 | 540 | 36 000 000 | 2 160 000 000 |
DW1500 | 11,25 | 60 | 675 | 45 000 000 | 2 700 000 000 |
DW2000 | 15 | 60 | 900 | 60 000 000 | 3 600 000 000 |
DW3000 | 22,5 | 60 | 1350 | 90 000 000 | 5 400 000 000 |
DW6000 | 45 | 60 | 2700 | 180 000 000 | 10 800 000 000 |
Ограничение размера транзакции накладывается на транзакцию или операцию. Оно не применяется к совокупности параллельных транзакций. Поэтому каждая транзакция может записать такой объем данных в журнал.
Сведения об оптимизации и минимизации объема данных, записываемых в журнал, см. в статье Оптимизация транзакций для хранилища данных SQL.
Предупреждение
Максимальный размер транзакции может быть достигнут только для распределенных таблиц HASH или ROUND_ROBIN, где распределение данных равномерно. Если транзакция неравномерно записывает данные в распределения, то вполне вероятно, что ограничение будет достигнуто до того, как размер транзакции станет максимальным.
Состояние транзакции
Пул SQL использует функцию XACT_STATE(), чтобы сообщить о неудачной транзакции с помощью значения −2. Это означает, что произошел сбой транзакции и она помечена только для отката.
Примечание
Использование функцией XACT_STATE значения -2 для обозначения неудачной транзакции отличается от поведения в SQL Server. SQL Server для представления нефиксируемой транзакции использует значение -1. SQL Server может допускать некоторые ошибки внутри транзакции, не помечая ее как нефиксируемую. Например, SELECT 1/0
вызовет ошибку, но не приведет к переходу транзакции в нефиксируемое состояние.
SQL Server также разрешает чтение в нефиксируемой транзакции. Однако пул SQL не позволяет это сделать. При возникновении ошибки в транзакции пула SQL транзакция автоматически перейдет в состояние -2, и вы не сможете выполнить дополнительные инструкции select, пока не произойдет откат этой инструкции.
Поэтому важно проверить код приложения, чтобы определить, используется ли в нем функция XACT_STATE(). Возможно, потребуется внести изменения в код.
Например, в SQL Server можно увидеть транзакцию такого рода.
SET NOCOUNT ON;
DECLARE @xact_state smallint = 0;
BEGIN TRAN
BEGIN TRY
DECLARE @i INT;
SET @i = CONVERT(INT,'ABC');
END TRY
BEGIN CATCH
SET @xact_state = XACT_STATE();
SELECT ERROR_NUMBER() AS ErrNumber
, ERROR_SEVERITY() AS ErrSeverity
, ERROR_STATE() AS ErrState
, ERROR_PROCEDURE() AS ErrProcedure
, ERROR_MESSAGE() AS ErrMessage
;
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRAN;
PRINT 'ROLLBACK';
END
END CATCH;
IF @@TRANCOUNT >0
BEGIN
PRINT 'COMMIT';
COMMIT TRAN;
END
SELECT @xact_state AS TransactionState;
В предыдущем коде появляется следующее сообщение об ошибке:
Сообщение 111233, уровень 16, состояние 1, строка 1 111233: текущая транзакция прервана, был выполнен откат всех изменений, находившихся в режиме ожидания. Причиной этой проблемы является то, что явный откат транзакции в состоянии, допускающем только откат, не доходит до стадии перед инструкцией DDL, DML или SELECT.
Вы не получите вывод функций ERROR_ *.
В пуле SQL этот код необходимо немного изменить:
SET NOCOUNT ON;
DECLARE @xact_state smallint = 0;
BEGIN TRAN
BEGIN TRY
DECLARE @i INT;
SET @i = CONVERT(INT,'ABC');
END TRY
BEGIN CATCH
SET @xact_state = XACT_STATE();
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRAN;
PRINT 'ROLLBACK';
END
SELECT ERROR_NUMBER() AS ErrNumber
, ERROR_SEVERITY() AS ErrSeverity
, ERROR_STATE() AS ErrState
, ERROR_PROCEDURE() AS ErrProcedure
, ERROR_MESSAGE() AS ErrMessage
;
END CATCH;
IF @@TRANCOUNT >0
BEGIN
PRINT 'COMMIT';
COMMIT TRAN;
END
SELECT @xact_state AS TransactionState;
Теперь можно наблюдать ожидаемое поведение. Ошибка в транзакции обрабатывается, и функции ERROR_ * предоставляют значения, как ожидалось.
Изменилось всего лишь то, что операция ROLLBACK с транзакцией должна произойти до чтения информации об ошибке в блоке CATCH.
Функция Error_Line()
Также следует отметить, что пул SQL не реализует и не поддерживает функцию ERROR_LINE(). Если она используется в коде, ее необходимо удалить, чтобы обеспечить совместимость с пулом SQL.
Вместо этого используйте в коде метки запросов, чтобы реализовать эквивалентную функциональность. Дополнительные сведения см. в статье Использование меток для инструментирования запросов в хранилище данных SQL.
Использование THROW и RAISERROR
THROW — это более современная реализация вызова исключений в пуле SQL, но поддерживается и RAISERROR. Тем не менее, существует ряд различий, которые заслуживают внимания.
- Для THROW номера определяемых пользователем сообщений об ошибках не могут быть в диапазоне от 100 000 до 150 000.
- Номера сообщений об ошибках RAISERROR не должны превышать 50 000.
- Не поддерживается использование sys.messages.
Ограничения
В пуле SQL есть несколько ограничений, относящихся к транзакциям.
Вот они:
- не поддерживаются распределенные транзакции;
- вложенные транзакции не разрешены;
- не допускается точки сохранения.
- не допускаются именованные транзакции;
- не допускаются помеченные транзакции;
- не поддерживаются операторы DDL, такие как CREATE TABLE, внутри определенной пользователем транзакции.
Дальнейшие действия
Узнайте больше об оптимизации транзакций, ознакомившись со статьей Оптимизация транзакций для хранилища данных SQL. Рекомендации по использованию пула SQL см. в статье Рекомендации по использованию пулов SQL.