Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Update строки во время удаления, отменяет удаление / 20 сообщений из 20, страница 1 из 1
25.07.2014, 17:00:05
    #38706226
Anton Laflaf
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Привет,

Такая ситуация: есть две таблицы: А и Б
Записи в Б могут удаляться двумя путями: напрямую из таблицы Б и при удалении родительской записи в А по foriegn key.

На таблице Б есть тригер, который апдейтит родительскую запись, при удалении записи в таблице Б.

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

Вопрос: правильно ли я понимаю причину не удаления записи из А? Что можно с этим сделать? Апдейт таблицы А нужен, от него не уйти.
...
Рейтинг: 0 / 0
28.07.2014, 08:32:25
    #38706962
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Anton Laflaf,

ИМХО, надо смотреть триггеры, когда они выполняются.
...
Рейтинг: 0 / 0
28.07.2014, 13:39:27
    #38707248
Anton Laflaf
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
roadster, и на А и на Б тригеры выполняются before

Но меня удивляет сам факт, что апдейт записи отменяет его удаление
...
Рейтинг: 0 / 0
28.07.2014, 13:55:44
    #38707271
rovan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Anton Laflaf,

ознакомься , может быть, найдёшь ответ на какие-то свои вопросы.
...
Рейтинг: 0 / 0
28.07.2014, 21:58:51
    #38707656
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Anton Laflaf,

тексты триггеров можно посмотреть?
...
Рейтинг: 0 / 0
29.07.2014, 10:59:50
    #38707881
Phoinix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Не вижу ничего необычного. PostgreSQL версионный в общем понимании этого слова;
Разбираем по операциям, очень грубо без сильной детализации:

- DELETE строки A таблицы T1;
- - Поиск строки A - нашли строку версии N (последнюю);
- - Запуск триггера BEFORE DELETE для строки A;
- - - DELETE строки B таблицы T2;
- - - - Поиск строки B - нашли строку версии M (последнюю);
- - - - Запуск триггера BEFORE DELETE для строки B;
- - - - - UPDATE строки A таблицы T1;
- - - - - - Поиск строки A - нашли строку версии N (последнюю, она еще не удалена, и доступна в пределах этой транзакции);
- - - - - - Запись обновленной строки A версии N + 1 (теперь эта последняя);
- - - - - - Помечаем строку A версии N как удаленную;
- - - - Возвращаем из триггера OLD и помечаем строку B версии M как удаленную;
- - Возвращаем из триггера OLD и помечаем строку A версии N как удаленную, повторный поиск новой версии строки N + 1 естественно не производится;

В итоге получаем:
строка A версии N - помечена как удаленная (2 раза);
строка B версии N - помечена как удаленная;
строка A версии N+1 - обновленная строка;

Можно теперь перестроить индексы.

Можно, конечно начать флейм о том какой PostgreSQL тупой, но не он осуществляет неконтролируемые перекрестные операции над строкой.

Собственно таков принцип работы триггеров BEFORE: сначала строку находим, исполняем триггер, потом производим операцию над найденной строкой, то что появилась новая версия строки - триггеру не ведомо.
...
Рейтинг: 0 / 0
29.07.2014, 13:34:27
    #38708092
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Phoinix,
"стройная теория, май френд, бат древо жызни, таки, зеленеет":


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
CREATE TABLE b
(
	b_id serial,
	a_id integer,
	bdata text,
	PRIMARY KEY (b_id)
	--DEFERRABLE INITIALLY DEFERRED
)
;

CREATE TABLE a
(
	a_id serial,	
	adata text,
	PRIMARY KEY (a_id)
	--DEFERRABLE INITIALLY DEFERRED
)
;
--=================================
-- Function: ftr_bu_b()
-- без изысков и забот о безусловной целостности:
CREATE OR REPLACE FUNCTION ftr_biud_b()
  RETURNS trigger AS
$BODY$
--BEFORE UPDATE,DELETE
DECLARE
BEGIN
	
	IF TG_OP = 'DELETE' THEN
		UPDATE a SET adata=a_id||'.'||(SELECT string_agg(b_id::text,'.') FROM b WHERE b.a_id=OLD.a_id)
		WHERE a.a_id=OLD.a_id;
		
		RETURN OLD;	
	ELSE
		UPDATE a SET adata=a_id||'.'||(SELECT string_agg(b_id::text,'.') FROM b WHERE b.a_id=NEW.a_id)
		WHERE a.a_id=NEW.a_id;
		IF TG_OP = 'UPDATE' THEN
			IF OLD.a_id<>NEW.a_id THEN
				UPDATE a SET adata=a_id||'.'||(SELECT string_agg(b_id::text,'.') FROM b WHERE b.a_id=OLD.a_id)
				WHERE a.a_id=OLD.a_id;
				RETURN OLD;	
			END IF;
		END IF;

		RETURN NEW;
	END IF;	

END;
$BODY$
  LANGUAGE plpgsql VOLATILE SECURITY DEFINER
  COST 100;


CREATE TRIGGER tr_biud_b BEFORE INSERT OR UPDATE OR DELETE
   ON b FOR EACH ROW
   EXECUTE PROCEDURE public.ftr_biud_b();
--======================================

INSERT INTO a (a_id) values (1),(2),(3),(4);
--test:
SELECT * FROM a;
-------------
INSERT INTO b (a_id,b_id) VALUES 
	(1,-1),(1,-2),(1,-3)
	,(2,-5),(2,-6),(2,-7)
	,(3,-8),(3,-9),(3,-10);
SELECT * FROM a;
DELETE FROM a WHERE a_id=1;
--test:
SELECT * FROM a;
---------------
/*
4;""
2;"2.-5.-6"
3;"3.-8.-9"
*/
-- кудынть делось  a_id = 1 ???? ЧЯДНТ



(?) ЧЯДНТ

2ТС приведите таки ваши триггера. там где-то есть, где покопаться.
...
Рейтинг: 0 / 0
29.07.2014, 15:12:33
    #38708239
Phoinix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
to qwwq

Вообще-то сарказм неуместен, а стоило бы немного почитать теорию.

С данным эффектом я сталкивался на версии на более ранних версиях.

Кстати в 9.3 этот эффект исправили путем запрета:

ERROR: tuple to be updated was already modified by an operation triggered by the current command
HINT: Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.

Какая версия у вас, тот еще вопрос.

to All

В любом случае. Суть не в том, как это происходит (хотя это полезно знать), а в том, что не контролируемые перекрестные/рекурсивные/каскадные команды - зло, и стоит быть несколько внимательным когда используются триггера.
...
Рейтинг: 0 / 0
29.07.2014, 16:00:23
    #38708311
Гость_0
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
PhoinixС данным эффектом я сталкивался на версии на более ранних версиях. Автор темы описывает другой случай и по его описанию воспроизвести у меня тоже не получается.
...
Рейтинг: 0 / 0
29.07.2014, 17:01:51
    #38708375
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Phoinix,
код где ?

что нужно AFTER -- известно.
что ошибка в BEFORE обсуждалась тут же (в т.ч. проблемы на версиях до 9.?. и запрет после) -- помню, но по тексту ошибки не нахожу. (они его не изменили ?)
Т.ч. чего именно она касается - не совсем ясно. //в нашем случае она не возникает.


зато в моем кейсе отваливается pk "on update cascade" -- при попытке апдейта пк в ведущей (А), что подтверждает рекомендацию в тексте ошибки
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
UPDATE a
SET a_id=-1
WHERE a_id=2;

SELECT * FROM b WHERE a_id IN (-1,2);
SELECT * FROM a WHERE a_id IN (-1,2);

UPDATE b SET a_id=-1  WHERE a_id=2;
SELECT * FROM b WHERE a_id IN (-1,2);
----------------------
select version();--"PostgreSQL 9.3.3 on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4), 64-bit"


-- т.е. все чудесатей и чудесатей (при хватании себя за хвост через before триггера)
...
Рейтинг: 0 / 0
29.07.2014, 23:12:17
    #38708605
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Phoinix- - Поиск строки A - нашли строку версии N (последнюю);
упс...
- - Запуск триггера BEFORE DELETE для строки A;
- - - DELETE строки B таблицы T2;
- - - - Поиск строки B - нашли строку версии M (последнюю);
- - - - Запуск триггера BEFORE DELETE для строки B;
- - - - - UPDATE строки A таблицы T1; очень странное рассуждение.
я не знаток постгре, но версионность сервера сказывается прежде всего на том, что читающие транзакции не мешают пишущим и не более того.
теперь поподробнее опишу что я вижу в Вашем рассуждении.
на месте вставленного мной упс найденная строка должна быть удалена, ну или "помечена" на удаление в ожидании коммита или роллбэка - это обязательное условие для срабатывания триггера. так вот эта "помеченная" на удаление строка может быть прочитана читающей транзакцией без проблем. но вот в последней выделенной строке должен, нет, просто обязан возникнуть лок конфликт. поэтому Ваши рассуждения сомнительны.
к тому же, если бы было возможным выполнение описанной Вами цепочки действий, то это означало бы,что пишущие транзакции не мешают пишущим, что повлекло бы за собой возможность нескольким транзакциям поменять запись одновременно, но тогда необходимо наличие механизма многоверсионности закоммиченных данных, я бы назвал это разными инкарнациями записи (грубо с одним значением ПК было бы несколько валидных и видных читателям записей). Вы не находите эту ситуацию глупой в разрезе существующей методологической базы реляционных СУБД?
...
Рейтинг: 0 / 0
30.07.2014, 08:19:12
    #38708666
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
Phoinix,

прошу прощения, написал глупость.
лок конфликт возникает в рамках межтранзакционного (если так можно выразиться) взаимодействия.
соответственно внутри транзакции все изменения будут видны, но тем не менее по триггеру бефор данные проапдейтятся, но потом удалятся (есть ещё вариант зацикливания, но автор топика об этом не говорит).
так что в любом случае описанная Вами ситуация невозможно. Необходимо смотреть триггеры, без них ничего не понятно.
...
Рейтинг: 0 / 0
30.07.2014, 11:25:42
    #38708877
Phoinix
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
По моему, сейчас все говорят не о том.

Резать проблему которая заведомо неверна - неправильно.
Решение простое: поменять BEFORE на AFTER для таблицы A.
Либо, если надо, разделить триггерную функцию на две, оставить часть отвечающую за проверку состояния перед удалением в BEFORE, а часть отвечающую за удаление связанных строк в AFTER.

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

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

В итоге получаем:
строка A версии N - помечена как удаленная (2 раза);
строка B версии N - помечена как удаленная;
строка A версии N+1 - обновленная строка;

Как будет на этот итог реагировать БД - логично не предсказуемо.

В своей практике я использовал не совсем верные решения с условной предсказуемостью для определенной версии, но при обновлении БД, практически всегда сталкивался с проблемами связанными с этими неправильными решениями.
...
Рейтинг: 0 / 0
30.07.2014, 11:51:01
    #38708922
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
PhoinixПо моему, сейчас все говорят не о том.без текстов триггеров разговаривать не о чем.
...
Рейтинг: 0 / 0
30.07.2014, 12:22:41
    #38708962
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
roadsterPhoinixПо моему, сейчас все говорят не о том.без текстов триггеров разговаривать не о чем.
не, дон местами прав, помню было где-то обсуждалово, но вот найти не могу (но что-то было, точно).

// там довольно нетривиально внутри всё происходило, "как не в одном потоке". если я правильно помню.

В моем случае кейс построен наполовину -- FK генерирует AFTER триггера:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT  t.tgname 
	,pg_get_triggerdef(t.oid) AS src
		FROM pg_class c, pg_trigger t 
		WHERE c.oid = t.tgrelid		
		AND relname = 'a';
-----------------------------------
"RI_ConstraintTrigger_a_109314";"CREATE CONSTRAINT TRIGGER "RI_ConstraintTrigger_a_109314" AFTER DELETE ON a FROM b NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_cascade_del"()"
"RI_ConstraintTrigger_a_109315";"CREATE CONSTRAINT TRIGGER "RI_ConstraintTrigger_a_109315" AFTER UPDATE ON a FROM b NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_cascade_upd"()"


т.е. если у ТС еще и каскады самописные и именно BEFORE -- может быть всякое интересное.

но хотелось бы посмотреть на тексты триггеров ТС, хотя бы модельные.
...
Рейтинг: 0 / 0
30.07.2014, 13:03:58
    #38709030
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
qwwq// там довольно нетривиально внутри всё происходило, "как не в одном потоке". если я правильно помню.при чём здесь потоки?
или я не понимаю о каких потоках идёт речь.
qwwqно хотелось бы посмотреть на тексты триггеров ТС, хотя бы модельные.я это и говорю, без них дальнейшее обсуждение бесполезно, догадок можно настроить кучу и все они окажутся неверными.
...
Рейтинг: 0 / 0
30.07.2014, 13:35:38
    #38709057
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
roadsterqwwq// там довольно нетривиально внутри всё происходило, "как не в одном потоке". если я правильно помню.при чём здесь потоки?
или я не понимаю о каких потоках идёт речь.
<>

то-то и оно, что вроде-бы не причём. (постгрес нигде ничего не параллелит сам) но код исполнялся в каком то странном порядке, как если бы исполнялся в разных потоках, или над разными перемеными. даже нотисы в неочевидном порядке лезли. в общем найти бы тот топег, где это всё это было с кодом, и с разбором -- было бы интересно сравнить с "диаграммой", взятой с потолка.
...
Рейтинг: 0 / 0
30.07.2014, 13:57:12
    #38709082
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
qwwqкод исполнялся в каком то странном порядке, как если бы исполнялся в разных потокахразные потоки и разные транзакции - это в моём понимании разные вещи.
...
Рейтинг: 0 / 0
30.07.2014, 14:06:29
    #38709090
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
roadsterqwwqкод исполнялся в каком то странном порядке, как если бы исполнялся в разных потокахразные потоки и разные транзакции - это в моём понимании разные вещи.

и ?
...
Рейтинг: 0 / 0
30.07.2014, 16:01:29
    #38709221
roadster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Update строки во время удаления, отменяет удаление
qwwqи ?это значит, что выполнение одной транзакции в разных потоках не должно сказаться на обеспечении целостности.
...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Update строки во время удаления, отменяет удаление / 20 сообщений из 20, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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