Гость
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать? / 8 сообщений из 8, страница 1 из 1
10.03.2020, 15:14
    #39935977
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
Скрипт написан на PHP.

В нем есть PHP-цикл, который выполняет порцию из ~1000 отдельных INSERT. Отдельные INSERT (а не один большой) сделаны вот по какой причине: некоторые INSERT могут завершиться ошибкой, например если значение вставляемого поля не уникально для поля с флагом UNIQUE (у меня это поле содержит uuid). Такие ошибки надо просто проигнорировать.

После этих INSERT-ов, в другую, сервисную, таблицу записывается последний корретно добавленый uuid. Это нужно из-за того, что данные для очередной порции INSERT могут вытягиваться с разных хостов, и для каждого такого хоста хранится свой uuid.

В любом случае, 1000 INSERT-ов и команда UPDATE для сохранения uuid, должны оборачиваться в одну транзакцию. Это нужно для сохранения консистенции данных. Проблема в том, что если при выполнении какого-то INSERT совпадет uuid, то будет ошибка, и будет откатана ВСЯ транзакция.

Чтобы это обойти, я хочу воспользоваться SAVEPOINT. То есть, сделать перед INSERT команду SAVEPOINT, и если INSERT завершился ошибкой, сделать ROLLBACK. Но я читаю документацию, и не могу понять, как это правильно сделать. У меня есть два варианта:

Вариант первый - простой:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
BEGIN;

цикл на ~1000

 SAVEPOINT beforeInsert;
 INSERT ...
 если неудачно
   ROLLBACK TO SAVEPOINT beforeInsert;

конец цикла

UPDATE last_uuid ...;
COMMIT;



Вариант второй - каждый раз удалять SAVEPOINT:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
BEGIN;

цикл на ~1000

 SAVEPOINT beforeInsert;
 INSERT ...
 если неудачно
   ROLLBACK TO SAVEPOINT beforeInsert;

 RELEASE SAVEPOINT beforeInsert

конец цикла

UPDATE last_uuid ...;
COMMIT;



Тут есть две непонятки.

Непонятка первая:

Вроде как написано, что не может быть несколько точек сохранения под одним и тем же именем, поэтому удаление SAVEPOINT в цикле - необходимо. С другой стороны, SAVEPOINT с одним и тем же именем должен быть _один_ в пределах одной транзакции, а мы в цикле таки создаем SAVEPOINT с одним и тем же именем. То есть тут вопрос, а можем ли мы в принципе создавать SAVEPOINT в пределах одной транзакции с одним и тем же именем, даже если мы его и удаляем, или надо все время генерить SAVEPOINT с разными именами ?


Непонятка вторая:

Я пока что склоняюсь, что вариант кода 2 должен быть рабочим. Но хотелось бы узнать, что лучше по производительности : постоянно создавать и удалять SAVEPOINT, или создавать SAVEPOINT с разными именами (например beforeInsert0, beforeInsert1, ... beforeInsertN), и они потом сами удалятся при завершении транзакции?
...
Рейтинг: 0 / 0
10.03.2020, 15:19
    #39935980
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
Что за форма регистрации,

Я бы просто проверял наличие конфликтующей записи перед тем как insert делать.
Будет СИЛЬНО быстрее чем savepoints которые дорогие изрядно.
Как вариат еще before insert триггер на таблице с такой же логикой (тогда с приложения вообще ничего проверять не надо).
...
Рейтинг: 0 / 0
10.03.2020, 15:44
    #39935989
Melkij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
Что за форма регистрации
Такие ошибки надо просто проигнорировать.

on conflict do nothing
...
Рейтинг: 0 / 0
10.03.2020, 16:20
    #39936008
mefman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
Что за форма регистрации,
ну и имечко у тебя
...
Рейтинг: 0 / 0
10.03.2020, 17:06
    #39936027
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
Melkij
Что за форма регистрации
Такие ошибки надо просто проигнорировать.

on conflict do nothing


там 9.1 версия и не меняется ))
...
Рейтинг: 0 / 0
10.03.2020, 17:35
    #39936045
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
mefman,

Я его получил когда глючила форма регистрации на этом форуме, теперь поменять не могу, ибо это не предусмотрено в движке.
...
Рейтинг: 0 / 0
10.03.2020, 18:16
    #39936058
Maxim Boguk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
Что за форма регистрации
mefman,

Я его получил когда глючила форма регистрации на этом форуме, теперь поменять не могу, ибо это не предусмотрено в движке.


Не могу исправить даже модератором, придется с этим жить.
...
Рейтинг: 0 / 0
10.03.2020, 21:19
    #39936099
OoCc
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
Что за форма регистрации,

Я бы загрузил весь батч во временную таблицу а потом бы пользовался нормальной реляционной алгеброй. Без ПХП лупов.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать? / 8 сообщений из 8, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]