LINUX.ORG.RU

Как отследить прогресс DELETE в PostgreSQL?

 


0

1

Существует ли какой то способ показывать пользователю на сколько процентов выполнен запрос? Например для «DELETE FROM items WHERE supplier_id = X;» показать сколько процентов уже удалено.

И сделать баттон «Cancel» на случай если пользователь захочет отменить? Ведь DELETE выполняется в транзакции изолированно и если отменить на середине всё восстановиться и ничего не удалится вообще? Достаточно ли просто убить скрипт по PID для того что бы отменить транзакцию?


Ответ на: комментарий от AnDoR

Ну я так понял что ничего для progress нет кроме для какой то там одной команды VACUUM. Остаётся только делать что то вроде «DELETE FROM items WHERE id IN (select id from items limit 1000)» несколько раз. В принципе это же наверное не проблема для производительности?

iluha16
() автор топика
Ответ на: комментарий от AnDoR

Разумеется, транзакция не закоммитится, если случилась какая-то ошибка. В этом вообще смысл рсубд.

Если транзакция заняла например 20 секунд и в самом конце процесс был убит и не закоммитилось что это значит? Что ещё 20 секунд потребуется какому то бэкграудному процессу что бы вернуть всё как было и это будет загружать процессорное время?

iluha16
() автор топика
Ответ на: комментарий от iluha16

Насколько я понимаю, так работает Oracle, но не Postgres. Postgres при обновлении данных записывает их новую версию, не удаляя старые, т.е. постгресу не понадобиться при откате транзакции восстанавливать предыдущие данные (в базе хранятся данные обоих версий, и устаревшую версию удалит Vacuum). А вот Oracle при обновлении данных их предыдущую версию записывает в журнал отката и обновляет их по месту, а если нужно будет откатиться - делает обратный процесс.

chimera19
()

В pg, как и в mysql при DELETE данные не удаляются, пока VACUUM/OPTIMIZE не сделаешь, так что теоретически можно откатить назад и после завершения DELETE.

Stanson ★★★★★
()

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

CREATE TRIGGER supplier_id_DEL_trg AFTER DELETE ON supplier_id
FOR EACH ROW
BEGIN
    INSERT INTO supplier_id_deleted(field1,field2,field3) VALUES(OLD.field1,OLD.field2,OLD.field3);
END; //
delimiter ;

В таблицу-дублёр можно записывать и логин того, кто удаляет, кстати, и время и всё такоэ.

Прогресс можно тупо обновлять периодически как

SELECT COUNT(*) FROM supplier_id_deleted;

Восстановить данные можно будет всегда, тупо скопировав их из таблички-дублёра.

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Как я понимаю пока транзакция не завершится полностью «SELECT COUNT(*) FROM supplier_id_deleted;» будет выдавать 0 (или сколько там было удалено раньше) т.к. транзакция выполняется изолированно. Разве нет?

iluha16
() автор топика

Отменить действие посреди выполнения выражения не получится. При необходимости можно накостылять решение (я бы вообще задумался над тем нужна ли отмена). Придется отказаться от быстрого удаления одним запросом нужных записей и удалять записи по одной в цикле. Заодно в цикле можно информировать пользователя о ходе выполнения операции. Коммитишь или роллбэчишь по выходу из цикла с проверкой причины выхода. Нужно подумать над тем, как досрочно выходить из цикла (при отмене действия), лучше, чтобы это было не в виде костыля, а решение, гармонично вписывающееся в систему (гармонично вписывающийся костыль, лол). Информирование пользователя можно разными способами сделать, я делал через pg_notify, на сколько я помню. Отдельный демон ловил уведомления, разбирал пэйлоад и информировал нужного пользователя (в моем случае это было веб-приложение, информирование происходило через веб-сокеты).

winlook38 ★★
()
Ответ на: комментарий от iluha16

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

В mysql это работает именно в процессе выполнения транзакции, и при удалении достаточно большого количества строк одним DELETE можно успеть заметить как меняется COUNT(*) в дублёре. Удалять нужно миллионы, а то и десятки миллионов строк, меньше просто не успеешь заметить, слишком быстро отрабатывает, если, конечно машина не атом какой-нибудь с базой на флешке и укушенной памятью.

Stanson ★★★★★
()
Ответ на: комментарий от iluha16

DELETE FROM items WHERE supplier_id = X;
Остаётся только делать что то вроде DELETE FROM items WHERE id IN (select id from items limit 1000)
Особенно после кривой поделки mysql.

Зато в «кривой» поделке, можно сделать проще и удобней

DELETE FROM items WHERE supplier_id = X LIMIT 1000;

surefire ★★★
()
Ответ на: комментарий от surefire

Ну да, в кривой поделке ещё INSERT ... SET ... удобнее. Только уж лучше написать десяток лишних букв чем терпеть всю эту путаницу и ограничения кривой поделки типа «references table(key)» на самом деле не создаёт foreign key а надо каким то другим способом, с транзакциями тоже путаница там какая то, куча форматов бд (engine=...) и в каждом свои ограничения. Даже интересно почему mysql весит 55M а postgres всего 18M, вроде как фич больше в postgres.

iluha16
() автор топика

Мне, честно говоря, не нравится сама идея

И сделать баттон «Cancel» на случай если пользователь захочет отменить

По-хорошему, надо делать запрос на подтверждение ПЕРЕД удалением. Да, можно аршинными буквами: «Вы ДЕЙСТВИТЕЛЬНО, находясь в здравом уме и твёрдой памяти, хотите удалить ...?» Если пользователь нажал «Да», а потом посреди удаления внезапно решил передумать - он ССЗБ, и не стоит городить кривые костыли для потакания его ССЗБ.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

По-хорошему, надо делать запрос на подтверждение ПЕРЕД удалением

В юзерфрендли-интерфейсах Cancel доступно после удаления.

Если пользователь нажал «Да»

Все же жмут автоматически, поскольку кодеры, не умеющие в UX, делают слишком много подтверждений.

x3al ★★★★★
()
Ответ на: комментарий от Shadow

SQL оптимизация 80 лвл

В смысле? Вроде ведь то, что ТСу нужно, и достаточно кросс-SQL'но...

Если есть другие варианты без хацкерства - не откажусь посмотреть. :)

Stanson ★★★★★
()
Ответ на: комментарий от Shadow

Я к тому, что это сильно замедлит процесс.

Да не особо, на самом деле. Если табличка-дублёр будет без индексов, то заметить глазами замедление можно будет только при удалении более миллиона записей. Кроме того, ТС'у же хочется прогресс наблюдать...

Stanson ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.