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


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

Gen2

DWU Лимит на распределение (ГБ) Количество дистрибутивов Максимальный размер транзакции (ГБ) # Строки для каждого распределения Максимальное количество строк на транзакцию
DW100c 1 шестьдесят шестьдесят 4 000 000 240,000,000
DW200c 1.5 шестьдесят девяносто 6 000 000 360 000 000
DW300c 2,25 шестьдесят 135 9,000,000 540,000,000
DW400c 3 шестьдесят 180 12,000,000 720,000,000
DW500c. 3,75 % шестьдесят 225 15 000 000 900,000,000
DW1000c 7.5 шестьдесят 450 30,000,000 1,800,000,000
DW1500c 11.25 шестьдесят 675 45,000,000 2,700,000,000
DW2000c 15 шестьдесят 900 60 000 000 3,600,000,000
DW2500c 18.75 шестьдесят 1125 75,000,000 4,500,000,000
DW3000c 22,5 шестьдесят 1350 90 000 000 5,400,000,000
DW5000c 37,5 шестьдесят 2,250 150,000,000 9,000,000,000
DW6000c 45 шестьдесят 2,700 180,000,000 10,800,000,000
DW7500c 56.25 шестьдесят 3375 225,000,000 13,500,000,000
DW10000c 75 шестьдесят 4 500 300 000 000 18,000,000,000
DW15000c 112,5 шестьдесят 6,750 450,000,000 27,000,000,000
DW30000c 225 шестьдесят 13,500 900,000,000 54,000,000,000

Ген1

DWU Лимит на распределение (ГБ) Количество распределений Максимальный размер транзакции (ГБ) # Строки для каждого распределения Максимальное количество строк на транзакцию
DW100 1 шестьдесят шестьдесят 4 000 000 240,000,000
DW200 1.5 шестьдесят девяносто 6 000 000 360 000 000
DW300 2,25 шестьдесят 135 9,000,000 540,000,000
DW400 3 шестьдесят 180 12,000,000 720,000,000
DW500 3,75 % шестьдесят 225 15 000 000 900,000,000
DW600 4,5 шестьдесят 270 18 000 000 1,080,000,000
DW10000 7.5 шестьдесят 450 30,000,000 1,800,000,000
DW1200 9 шестьдесят 540 36 000 000 2,160,000,000
DW1500 11.25 шестьдесят 675 45,000,000 2,700,000,000
DW2000 15 шестьдесят 900 60 000 000 3,600,000,000
DW30000 22,5 шестьдесят 1350 90 000 000 5,400,000,000
DW60000 45 шестьдесят 2,700 180,000,000 10,800,000,000

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

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

Предупреждение

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

Состояние транзакции

Пул SQL использует функцию XACT_STATE(), чтобы сообщить о неудачной транзакции с помощью значения -2. Это значение означает, что транзакция завершилась сбоем и помечена только для отката транзакции.

Примечание.

Использование -2 функцией XACT_STATE для обозначения неудачной транзакции представляет другое поведение 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;

Приведенный выше код содержит следующее сообщение об ошибке:

Msg 111233, Level 16, State 1, Line 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_* предоставляют значения, как и ожидалось.

Единственное, что изменилось, это то, что откат транзакции должен был произойти до того, как было бы прочитано сообщение об ошибке в блоке CATCH.

функция Error_Line()

Также следует отметить, что пул SQL не реализует или поддерживает функцию ERROR_LINE(). Если у вас есть этот код, необходимо удалить его, чтобы он соответствовал пулу SQL.

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

Использование THROW и RAISERROR

THROW — это более современная реализация для создания исключений в пуле SQL, но также поддерживается RAISERROR. Есть несколько различий, на которые стоит обратить внимание.

  • Определяемые пользователем номера сообщений об ошибках не могут находиться в диапазоне 100 000 – 150 000 для THROW.
  • Сообщения об ошибках RAISERROR имеют фиксированное значение на уровне 50 000.
  • Использование sys.messages не поддерживается

Ограничения

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

Они приведены следующим образом:

  • Нет распределенных транзакций
  • Не разрешены вложенные транзакции
  • Нет разрешенных точек сохранения
  • Без именованных транзакций
  • Нет помеченных транзакций
  • Нет поддержки DDL, например CREATE TABLE внутри определяемой пользователем транзакции

Дальнейшие действия

Чтобы узнать больше об оптимизации транзакций, см. в разделе Рекомендации по лучшим практикамтранзакций. Дополнительные сведения о наиболее эффективном использовании пула SQL см. в рекомендациях по пулам SQL.