powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
8 сообщений из 8, страница 1 из 1
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
    #39935977
Скрипт написан на 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
ROLLBACK транзакций в цикле для PosgreSQL - как правильно делать?
    #39935980
Фотография Maxim Boguk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что за форма регистрации,

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

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

on conflict do nothing


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

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

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


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

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


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