Форум: "Базы";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];
ВнизКто понимает смысл ошибки "Таблица мутирует" ? Найти похожие ветки
← →
ANB © (2006-09-05 16:18) [40]
> См. [27] последнее предложение и [30].
Согласен. Но к каждому триггеру придется тогда добавить еще и хранимку.
> Если базы разные, а потом репликация в главную, мое имхо,
> лучше сделать составной ПК из id филиала и сиквенса.
1) Базы, есно, разные.
2) Составной PK не сильно кузяво (в связке из 30-40 таблиц да с извратами это сильно неудобно будет)
3) Исторически сложилось, млин. Достаточно было запихать номер филилала в млдашие ращряды ID, а не в старшие (ограничив собственно ID 20000000) и сиквенса бы хватило весьма надолго. Но - см. начало фразы.
← →
ANB © (2006-09-05 16:20) [41]
> Вот из-за этой зависимости результата от очередности изменения
> записей Oracle и выдает ошибку про "мутации" :)
Вместо этого могли бы описать эту проблему в доке и не резать возможность селекать в своей таблице, когда порядок изменения строк не важен.
← →
evvcom © (2006-09-05 16:26) [42]> [38] ANB © (05.09.06 16:13)
Ну да. Здесь функция вызывается для каждой строки при апдейте. Естественно таблица уже меняется.
> [37] Petr V. Abramov © (05.09.06 16:12)
> P.S. не люблю триггеры, запутывают они систему, а во-вторых,
> если в случае крайней необходимости надо руками данные
> подправить, может нехорошо получиться
Чтобы обеспечить целостность системы, когда возможностей констрейнтов уже недостаточно, предпочитаю писать триггеры. С триггерами можно и руками подправить, если они корректно написаны. А вот с ХП можно нарваться и на поломку целостности, если кто-то из любителей поправить руками (ну я, например) вдруг не знает, что делать это с данной таблицей категорически запрещается.
← →
Val © (2006-09-05 16:30) [43]>[41] ANB © (05.09.06 16:20)
это описанов доке, в разделе о триггерах, описано и решение.
← →
evvcom © (2006-09-05 16:32) [44]> [40] ANB © (05.09.06 16:18)
> Но к каждому триггеру придется тогда добавить еще и хранимку.
Можно и одну написать, если очень лень, в которой SQL формировать динамически. Кстати, а попробуй динамический SQL прямо в триггере. Есть подозрение, что он будет выполняться также в отдельной транзакции. Не утверждаю, но вдруг? На Оракле я такое еще не проверял.
← →
evvcom © (2006-09-05 16:35) [45]> [41] ANB © (05.09.06 16:20)
> Вместо этого могли бы описать эту проблему в доке и не резать
> возможность селекать в своей таблице, когда порядок изменения
> строк не важен
А прикинь, я когда с этим впервые столкнулся, доков на эту тему не читал. Вот умолчал бы Оракл об этом, и я бы долго бы еще тогда пытался понять, почему получаю в селектах не то, что ожидаю. А так полез разбираться и согласился с ними.
← →
ANB © (2006-09-05 16:52) [46]
> что он будет выполняться также в отдельной транзакции
не в отдельной.
> это описанов доке, в разделе о триггерах, описано и решение.
Ну ктоб спорил. "Мы сделали криво, вот вам руководство, как наши кривые руки обойти на 15 листах".
> evvcom © (05.09.06 16:26) [42]
+1.
← →
Val © (2006-09-05 16:58) [47]>[46] ANB © (05.09.06 16:52)
> "Мы сделали криво...
Это ВЫ так думаете, а кто-то думает иначе. Посоветуете подкрутить сервер под желания каждого разработчика? Да ну его нафиг, такое чудовище.
← →
evvcom © (2006-09-05 17:06) [48]> [46] ANB © (05.09.06 16:52)
> "Мы сделали криво,
Я тоже с этим не согласен. Нормально сделали.
← →
ANB © (2006-09-05 17:14) [49]
> Val © (05.09.06 16:58) [47]
> evvcom © (05.09.06 17:06) [48]
Так чего же тут нормального ?
Как мы выяснили на примере FB, логического противоречия никакого нет.
Да, если убрать ошибку, то в НЕКОТОРЫХ случаях возможна неоднозначность операции из-за непредсказуемости последовательности обработки строк таблицы при апдейтах и удалениях. Но :
1) далеко не всегда эта последовательность важна
2) коллизия возможна только при групповом обновлении/удалении записей и легко могла бы быть при надобности ликвидирована использованием курсора (групповой инсерт легко регулируется order by в запросе - никакой неоднозначности).
У меня такое впечатление, что оракл просто по техническим причинам (из-за существующего механизма транзакций) не готов работать с измененными/удаленными записями в рамках одного оператора. Посему, чтобы не мучится, сделали генерацию ошибки и свалили все проблемы на прикладных программистов.
Некузяво как то.
← →
evvcom © (2006-09-05 17:29) [50]> [49] ANB © (05.09.06 17:14)
> логического противоречия никакого нет.
Есть. Вникни в пример [39]. Если FB такое позволяет, поэкспериментируй на нем. Возможность получить разные результаты выполнения - это уже баги. Оракл эту возможность пресёк.
> 1) далеко не всегда эта последовательность важна
Если не важна, обходи эту ситуацию известными способами.
> 2) коллизия возможна только
ну ведь возможна же! :)
> групповой инсерт легко регулируется order by в запросе -
> никакой неоднозначности
AFAIR, order by в инсерте недопустим.
> из-за существующего механизма транзакций
А транзакция тут при чем? Речь идет о групповой замене за один присест, в одном операторе.
> и свалили все проблемы на прикладных программистов.
В твоем случае, ты сам вроде как признался, виноваты сами прикладные программисты. Ошибка проектирования базы. Отсюда и проблемы, которые отпали бы, построив базу "правильно".
← →
ANB © (2006-09-05 17:44) [51]
> AFAIR, order by в инсерте недопустим.
хм. напиши групповой инсерт без селекта.
> построив базу "правильно".
Имхо - правильно, это использовать триггера. А от этого сплошь и рядом приходится отказываться или городить кучу объектов для обхода
> Если FB такое позволяет, поэкспериментируй на нем. Возможность
> получить разные результаты выполнения - это уже баги. Оракл
> эту возможность пресёк.
Мне подход FB больше нравится. А такое пресекание "отберем у всех в Москве спички, чтобы ничего не спалили в деревне Гадюкино" режет фукциональность.
> А транзакция тут при чем? Речь идет о групповой замене за
> один присест, в одном операторе
ПОСЛЕ оператора до коммита в таблице лежат новые данные, в RBS - старые.
А вот где что лежит во время выполнения оператора - х.з. (знаний маловато).
← →
ANB © (2006-09-05 18:56) [52]Кстати, по поводу неоднозначности.
Вот такой оператор :
update Table2 set Status = rownum
будет выполнен без проблем, хотя его результат тоже неоднозначен и зависит от настроения сервера.
Однако этот случай задокументирован, ошибка не генерится.
← →
Desdechado © (2006-09-05 19:15) [53]ANB ©
Ты скажи, ты завел этот топик, чтобы высказать свое возмущение или послушать объяснения?
Возмущения понятны, но, имхо, от них все равно ничего не изменится. Прими механизм как данность. Просто теперь им не выгодно менять логику поведения сервера, слишком много у всех заточек на старый механизм, а обратной совместимости никто не отменял.
Выгоднее делать новые фичи, чем Ларри успешно занимается.
← →
ANB © (2006-09-05 19:23) [54]
> Выгоднее делать новые фичи, чем Ларри успешно занимается.
Ну так прагму бы добавили для тех, кому неохота возится с этой ошибкой. Автономная транзакция же исправляет ситуацию.
> Ты скажи, ты завел этот топик, чтобы высказать свое возмущение
> или послушать объяснения?
Высказать возмущения, послушав объяснения (может я чего не догонял или в FB таже картина). Я то считал, что кроме оракла сия ошибка больше нигде не встречается.
← →
Desdechado © (2006-09-05 19:31) [55]> Автономная транзакция же исправляет ситуацию.
Это заблуждение.
← →
ANB © (2006-09-05 19:40) [56]
> > Автономная транзакция же исправляет ситуацию.
> Это заблуждение.
Функция перестала падать.
Ща доработает - на триггере потренируюсь. Но эта прагма автоматически включает чтение старых данных.
← →
Val © (2006-09-05 19:44) [57]>включает чтение старых данных
может, отключает чтение новых?
← →
Desdechado © (2006-09-05 19:46) [58]> Функция перестала падать.
А теперь подумай, что будет, если надо будет откатить всю транзакцию, а не отдельные ее автономности?
И ты поймешь, что заблуждался относительно "решения пролемы". Ты ее только замаскировал и углубил.
← →
ANB © (2006-09-05 19:51) [59]CREATE OR REPLACE TRIGGER tr_table2
BEFORE UPDATE
ON table2
FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
v_cnt INTEGER;
BEGIN
SELECT COUNT (*)
INTO v_cnt
FROM table2 t2
WHERE t2.parent_id = :NEW.parent_id;
END;
Вот этот триггер работает. Убираем прагму - валится.
> если надо будет откатить всю транзакцию, а не отдельные
> ее автономности?
Что откатывать после селекта ?
Кстати, таки доп. неудобство. Мало того, что я не могу производить проверки с учетом уже измененных записей (хотя всего одна то меняется, здесь то зачем мутация ?), так еще изменять данный в общем контексте транзакции не смогу.
> может, отключает чтение новых?
да какая разница. пусть будет "отключает".
← →
ANB © (2006-09-05 19:54) [60]Завели бы прагму типа "грязное чтение чего попало". кто хочет иметь такой результат и работать без генерации ошибки - самостоятельно включает. Хочешь по старому - без прагмы все по старому и работает.
Зажрался просто оракл.
← →
Petr V. Abramov © (2006-09-05 23:40) [61]> С триггерами можно и руками подправить, если они корректно написаны. А
> вот с ХП можно нарваться и на поломку целостности, если кто-то из
> любителей поправить руками (ну я, например) вдруг не знает, что делать
> это с данной таблицей категорически запрещается.
это уже оргметодами решается. т.е любители подправить руками, которые не знают, не должны иметь возможность это сделать. А необходимость сия на моей памяти возникала только в случае, когда облажались с кодом и надо быстро привести базу в состояние, когда она в целости и непротиворечивости.
Проблема чуть глубже. вотя как кодер, когда говорю update, знаю, что поменяются записи в соответствии с set и where, и больше ничего. А так прежде чем писать update, теоретически должен предугадать фантазию триггерописателей на срок службы системы. Проблема ессно вылезает, когда таблица стоИт на грани полномочий двух разработчиков.
> что оракл просто по техническим причинам (из-за существующего
> механизма транзакций) не готов работать с измененными/удаленными
> записями в рамках одного оператора.
на мое ИМХО технических проблем нет. Такой же Plssql-ный объект, как и ХП и пакет. А от plssql до мехпнизма управления транзакциями - 2 лаптя по карте. Работает-то он все равно в терминах блоков. Может, конечно просто поленились к релизу глючок какой исправить, и оказалось, что оно на надо, пусть так живет, приложения надежней будут
← →
tesseract © (2006-09-06 00:08) [62]> Выгоднее делать новые фичи, чем Ларри успешно занимается.
да нет в моде упрощёнка, а на кой он MySQL к рукам прибрал?
> я не могу селекать в триггере изменяющуюся таблицу ?
Потому что происходит перестройка файловой структуры базы, что после этого выйдет, и какого цвета, никто не знает, это только dbf сильно предсказуем.
> Есно, при триггере уровня строки у меня селект завалится.
> Однако, если бы он не завалился, а возвращал мне смесь новых
> и старых строк - это бы меня вполне устроило.
А зря, менеджеров, не устраивает, в 99% случаев.
> Вот в IB она никогда не мутирует в режиме ReadCommitted.
ReadCommited для того и создан, максимум производительности при минимуме проблем. Фактически неявная неблокирующая транзакция, пока не подтвердишь данные можно считать старые.
> > что оракл просто по техническим причинам (из-за существующего
>
> > механизма транзакций) не готов работать с измененными/удаленными
>
> > записями в рамках одного оператора.
> на мое ИМХО технических проблем нет. Такой же Plssql-ный
> объект, как и ХП и пакет. А от plssql до мехпнизма управления
> транзакциями - 2 лаптя по карте. Работает-то он все равно
> в терминах блоков. Может, конечно просто поленились к релизу
> глючок какой исправить, и оказалось, что оно на надо, пусть
> так живет, приложения надежней будут
Как-раз таки технические проблемы ИМХО здесь и есть, с ними вроде только DB2 в состояниии справиться.
← →
Petr V. Abramov © (2006-09-06 00:47) [63]> Как-раз таки технические проблемы ИМХО здесь и есть, с ними вроде
> только DB2 в состояниии справиться.
тот же FB пожеланиям некотрых трудящихся удовлетворяет. А в чем, на Ваш взгляд, технические проблемы-то? Давайте погадаем :)
> пока не подтвердишь данные можно считать старые.
только это небесплатно в плане ресурсов-то
← →
Petr V. Abramov © (2006-09-06 01:44) [64]да ладно. много много в Oracle несовершенства, но у него есть такое же гадкое св-во, как у Windows - люди матерятся на глюки (сабж - не глюк :), но на другие продукты не переходят :)
← →
ANB © (2006-09-06 09:21) [65]
> tesseract © (06.09.06 00:08) [62]
Во. Наконец то опытный спец пришел. Как чувствовал, что просто забили на баг, оформили исключением и сделали его фичей.
> (сабж - не глюк :),
- конечно, не глюк - глюк, это непойманный баг. А пойманный, заткнутый и документированный - это уже фича.
Продолжил эксперименты :
При наличии указанных выше таблиц и триггера (без прагмы) вот это работатет :
insert into table2 (ID, Parent_ID, Status)
values (10001, 1, 2)
insert into table2 (ID, Parent_ID, Status)
select 10002, 1, 3 from dual
insert into table2 (ID, Parent_ID, Status)
select rownum + 10010, rownum + 10010 - 1, decode(mod(rownum,2),0,4,5) from dual
connect by level <= 1000
А вот это - уже нет :
update table2 T2
set Status = t2_prev_status(t2.PARENT_ID)
where ID = 1
Кстати, в похожей ситуации на 8-ке инсерт нескольких записей не работал. Так что есть надежда, что таки потихоньку доведут до ума.
Таки не понятно - почему проходит массовый инсерт и не работает апдейт одной записи ? Триггер уровня строки до. Т.е. ораклу должно быть все понятно, никакой неоднозначности - какая мутация то ?
← →
evvcom © (2006-09-06 10:27) [66]> [51] ANB © (05.09.06 17:44)
> А вот где что лежит во время выполнения оператора - х.з.
> (знаний маловато).
Я думаю, все там же. Только часть данных уже изменилась, а части еще предстоит. Кроме того выставляется внутренний флаг, что таблица уже изменяется, он-то и анализируется.
> [53] Desdechado © (05.09.06 19:15)
Поддерживаю.
> [56] ANB © (05.09.06 19:40)
> Но эта прагма автоматически включает чтение старых данных.
Она не включает. Просто автономной транзакции не доступны изменения, сделанные в первичной транзакции, а потому для нее
таблица не изменяется.
← →
ANB © (2006-09-06 10:31) [67]
> А зря, менеджеров, не устраивает, в 99% случаев.
Менеджерам важны данные в отчетах и гриде. Триггер их никак волновать не должен. А если по логике триггера мне все равно, в каком порядке изменяются данные, главное - чтобы давали читать уже измененные ?
← →
evvcom © (2006-09-06 10:35) [68]> [67] ANB © (06.09.06 10:31)
Ну сделай табличку в пакете, в нее пиши изменения, а в автономной внешне джойни ее с оригинальной. И будет тебе все, как хочешь.
← →
ANB © (2006-09-06 10:43) [69]
> evvcom © (06.09.06 10:35) [68]
> > [67] ANB © (06.09.06 10:31)
>
> Ну сделай табличку в пакете, в нее пиши изменения, а в автономной
> внешне джойни ее с оригинальной. И будет тебе все, как хочешь.
>
Способов изгала то много. Для проверки на целостность дерева можно и стандартным обходом обойтись. Можно и вообще триггера не использовать.
И запретить использовать функции в DML.
← →
Petr V. Abramov © (2006-09-06 13:37) [70]> ПОСЛЕ оператора до коммита в таблице лежат новые данные, в RBS -
> старые. А вот где что лежит во время выполнения оператора - х.з. (знаний маловато).
в RBS лежат change vectors, изменения данных. А "во время измения" - в тех блоках, которые уже поменялись - новые данные, в которых еще не поменялись - старые :) Второй свежести данных не бывает :) То есть триггер в процеесе выполнения запроса относительно легко может получить старые данные (обычным consistent read, небесплатной процедурой), а новые - никак, потому что не все блоки еще обновились. Может, еще именно из-за consistent read не стали они связываться и сделали выдачу ошибки, тем более, что про винигрет уже много тут говорилось
← →
Petr V. Abramov © (2006-09-06 14:05) [71]> ANB ©
если интересует, что там происходит "во время выполнения оператора", то
1. сделай триггер, который после изменения двух-трех записей повесит сессию (dbms_lock.sleep)
2. поизучай заголовки блоков (v$bh). вечерком могу поискать, как скинуть дамп блока в trace, сейчас просто убегаю.
Счастливых анатомических исследований :)))
← →
Андрей Пазик (2006-09-06 14:43) [72]IB/FB вообще нарушает базовые принципы SQL. Например. Есть у вас поле с уникальным индексом. делаем update sometable set unq_field = unq_field + 1
И получаем детскими граблями! Потому что ограничения целостности проверяются тут на onrowChange, а не на onStatementFinish.
← →
evvcom © (2006-09-06 15:01) [73]> [72] Андрей Пазик (06.09.06 14:43)
Не знаю как этот случай описан в базовых принципах, а Оракл без специального аттрибута в ключе тоже по рукам даст за такое.
← →
Desdechado © (2006-09-06 15:39) [74]> поле с уникальным индексом. делаем update sometable set unq_field = unq_field + 1
Смысл этого запроса?
← →
Petr V. Abramov © (2006-09-06 22:05) [75]> Не знаю как этот случай описан в базовых принципах, а Оракл без
> специального аттрибута в ключе тоже по рукам даст за такое.
и по умолчанию бьет. dererrable initially defrerred появилось только в 8-ке (и, что странно, в той же версии оно уже работало :)
← →
Sergey13 © (2006-09-07 08:19) [76]> [75] Petr V. Abramov © (06.09.06 22:05)
Хм. А у меня 8.1.7 съел и не подавился.
Страницы: 1 2 вся ветка
Форум: "Базы";
Текущий архив: 2006.11.05;
Скачать: [xml.tar.bz2];
Память: 0.63 MB
Время: 0.045 c