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


Использование транзакций в пуле 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.