Транзакции в Postgres

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

В Postgres в каждом отдельном операторе заложена идея о том, что этот оператор выполняется в транзакции. Если мы напишем два простых оператора UPDATE, они могут выглядеть примерно так:

UPDATE table1 SET column1 = 100.00
    WHERE id = 3;

UPDATE table1 SET column1 = 100.00
    WHERE id = 4;
Войти в полноэкранный режим Выйти из полноэкранного режима

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

BEGIN;
UPDATE table1 SET column1 = 100.00
    WHERE id = 3;
COMMIT;

BEGIN;
UPDATE table1 SET column1 = 100.00
    WHERE id = 4;
COMMIT;
Вход в полноэкранный режим Выход из полноэкранного режима

Блок транзакции — это набор запросов, выполняемых между командами BEGIN и COMMIT. Когда вы не указываете ни одну из этих команд, они неявно окружают каждую команду.

Мы можем отменить это поведение по умолчанию, чтобы указать различные блоки транзакций с помощью команд BEGIN и COMMIT. Идея заключается в том, что мы можем выполнять несколько операций над базой данных одновременно. Это полезно в тех случаях, когда промежуточные операции могут завершиться неудачей, и мы не хотим, чтобы выполнялись последующие команды. Вся «транзакция» не произойдет.

Ниже вы можете видеть, что в этом сценарии мы фактически указали BEGIN и COMMIT. Теперь, как блок транзакции, эти два будут «зафиксированы» в базе данных и видны в одно и то же время.

BEGIN;
    UPDATE table1 SET column1 = 100.00
        WHERE id = 3;

    UPDATE table1 SET column1 = 50.00
        WHERE id = 4;
COMMIT;
Вход в полноэкранный режим Выйти из полноэкранного режима

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

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

BEGIN;
    CREATE TABLE table2 (
       column1 datatype(length) column_contraint,
       column2 datatype(length) column_contraint,
    );
    // add some data into table2

    DROP table table1;

    SELECT * INTO table1 FROM table2;

COMMIT;
Войти в полноэкранный режим Выйти из полноэкранного режима

Откат

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

Оцените статью
devanswers.ru
Добавить комментарий