Страница 1 из 2
Умирают индексы и внешние ключи
Добавлено: 21 фев 2008, 12:07
Enklgd01
InterBase 7.5.0.174
Ситуация по логике: добавляется запись, потом вызывается хранимая процедура, которая по некоторой логике эту запись разбивает на несколько (в исходной записи есть число, после разбития сумма чисел в полученных записях равно исходной). Временами возникают условия, при которой разбить на несколько записей не удается, в этом случае процедура вызывает EXCEPTION EX_NAME;
Теперь проблема: если добавить запись, сделать Commit, а потом вызвать процедуру, то просто получаю Exception.
Если добавить запись и НЕ делая Commit вызвать процедуру, то:
1) "слетают" (corrupt) все внешние ключи в этой таблице
2) слетают все индексы этой таблицы, в которых есть указание одного из полей внешних ключей
3) умирает часть внешних ключей в других таблицах (эти таблицы в процедуре используются только для SELECT)
Попытки использовать в приложении SavePoint никаких результатов не дали.
Временное решение получено: расстановка в процедуре некоторого кол-ва флагов с дополнительными SELECT'ами, но из-за этого увеличилось время выполнения процедуры.
Непонятна причина падения индексов, несмотря на то, что всё, что эта транзакция делает RollBack при получении ошибки.
При этом, обращу еще раз внимание: если сделать Commit записи, а потом начать новую транзакцию -- всё работает без повреждений базы, если транзакцию не коммитить, а пытаться провести действия сразу после добавления, то индексы умирают.
PS: для доступа в приложении используется IBX11
Добавлено: 21 фев 2008, 12:48
Merlin
В процедуре используются Savepoints? Их реализация в PSQL некорректна. В FB поэтому разрешены только на клиенте.
Добавлено: 21 фев 2008, 13:08
Enklgd01
Merlin писал(а):В процедуре используются Savepoints? Их реализация в PSQL некорректна. В FB поэтому разрешены только на клиенте.
нет, использование SavePoint пробовалось в клиентском приложение, не в хранимой процедуре.
Добавлено: 21 фев 2008, 13:16
Merlin
Погляди на сайте, не было ли сервис-паков для 7.5, я с IB не работаю, не помню какие версии патчились.
Добавлено: 21 фев 2008, 13:42
kdv
www.ibase.ru/devinfo/allversions.htm
апдейты на офсайте. Надо 7.5.1 SP 1
Если добавить запись и НЕ делая Commit вызвать процедуру, то:
1) "слетают" (corrupt) все внешние ключи в этой таблице
что-то страшное... либо какой то неизвестный ранее баг (нам не попадалось), либо стечение обстоятельств, и на машинке есть кривое железо.
Добавлено: 21 фев 2008, 14:19
Enklgd01
kdv писал(а):и на машинке есть кривое железо
думалось и такое, но... проверялось на 3-х разных машинках у себя и на 2-х у других людей... в каждом тесте каждая машинка являлась сервером (они вообще никак не связаны между собой)... и везде такая ситуация...
Добавлено: 21 фев 2008, 15:55
kdv
значит обновлять надо.
Добавлено: 27 фев 2008, 10:20
Enklgd01
проверки на InterBase 7.5.0.174 и на InterBase 7.5.1.162 дали одинаковые результаты
использование советов из
http://ibase.ru/devinfo/ibstp.htm также не дало результатов
может быть ошибка возникает при большом кол-ве вложенности вызовов процедур:
главная процедура -> процедура 2 -> процедура 3 -> процедура 4 -> процедура 5 (в которой появляется Exception)
?
до тех пор пока Exception вызывался в 3-ем уровне, проблем не возникало, но заказчиком были поставлены требования, которые привели к такому вот разрастанию вызовов (в БД вшита вся логика, а в ПО идет просто вызов процедур без каких-либо проверок, по требованию заказчика)
но на какие-либо ограничения по вложенности процедур не удалось найти информации
из попыток локализовать ошибку выяснилось, что именно в таком вызове "процедура 5" индексы становятся corrupt, при вызове "процедура 5" из главной процедуры (там где эти вызовы по логике нужны) появляется Exception, но индексы остаются целыми
PS: к "парку" тестовых машин добавилось 2 ноутбука (тестировалось на InterBase 7.5.1.162) -- результаты точно такие же...
Добавлено: 29 фев 2008, 00:59
kdv
вполне может быть, что из-за вложенности - на каком-то уровне "ломаются" сэйвпойнты, и все. могу только сказать, что такой уровень вложенности очень редок.
Добавлено: 11 апр 2008, 01:05
Felix1978
Да тоже столкнулись с подобной проблемой, вложенность тут не причем.
Создаем таблицы
CREATE TABLE A (
ID INTEGER NOT NULL,
B_ID INTEGER
);
ALTER TABLE A ADD CONSTRAINT PK_A PRIMARY KEY (ID);
CREATE TABLE B (
ID INTEGER NOT NULL,
NAME VARCHAR(20)
);
INSERT INTO B (ID, NAME) VALUES (1, 'www');
COMMIT WORK;
ALTER TABLE B ADD CONSTRAINT PK_B PRIMARY KEY (ID);
ALTER TABLE A ADD CONSTRAINT FK_A_1 FOREIGN KEY (B_ID) REFERENCES B (ID);
И процедуру:
CREATE PROCEDURE PP (
ID INTEGER)
AS
begin
update a set id=id where id=:id;
update a set b_id=1 where id=:id;
exception EX_PERM;
end
И выполняем в одной транзакции:
INSERT into A (id, b_id) values (1,null);
EXECUTE PROCEDURE pp(1);
делаем commit;
все FK битый,
select * from a where b_id is null ничего не дает, хотя запись есть.
Если сделать commit после вставки все ок.
Если в процедуре убрать первый UPDATE тоже все ок.
Обновлять можно любое поле не id результат тотже!
Добавлено: 11 апр 2008, 11:22
hvlad
Felix1978 писал(а):Да тоже столкнулись с подобной проблемой
На каком сервере ?
Добавлено: 11 апр 2008, 11:22
Merlin
Выпрямляю руки, дёшево
Felix1978 писал(а):
CREATE TABLE B (
ID INTEGER NOT NULL,
NAME VARCHAR(20)
);
INSERT INTO B (ID, NAME) VALUES (1, 'www');
COMMIT WORK;
Таблица битая уже в этот момент. Дальнейшие приключения с FK могут быть следствиями, хотя может и сами по себе мальчики (С). Структуры метаданных создаются на коммите, сам Create - только протокол о намерениях

То есть, перед Insert должен быть ещё один коммит. Ну и создание констрайнтов тоже следует коммитить перед DML-операциями.
Добавлено: 11 апр 2008, 13:34
Felix1978
Таблица битая уже в этот момент. Дальнейшие приключения с FK могут быть следствиями, хотя может и сами по себе мальчики (С). Структуры метаданных создаются на коммите, сам Create - только протокол о намерениях То есть, перед Insert должен быть ещё один коммит. Ну и создание констрайнтов тоже следует коммитить перед DML-операциями.
Умник, проблема не в этом создай все с коммитами после каждого действия. Можешь потом подключиться снова и выполнить 3 действия результат битый ключ!
Проблема в том, что при вызове Insert->процедура на update->потом commit и все ж....
Причем в процедуре должно быть 2 update этой записи. А если сделать commit между insert и процедурой все ок!
Есть мысли у кого-нибудь?
Добавлено: 11 апр 2008, 13:43
kdv
Есть мысли у кого-нибудь?
1. не делать update одних и тех же записей в одной транзакции 2 или более раз
2. не писать такие процедуры, или пытаться все обрамлять begin/end или похоже
3. поумерить пыл в общении с участниками форума. Это уже предупреждение.
Добавлено: 11 апр 2008, 13:50
Felix1978
1. Причем тут begin end?
2. Может вообще на IB не писать?
3. Я просил конструктивный совет, что значит не делать? это явный глюк или где то есть официальная информация, что нельзя в процедуре делать 2 update одной записи?
Добавлено: 11 апр 2008, 13:54
Felix1978
Кстати проблема на ib 7.5. и на ib 2007.
Добавлено: 11 апр 2008, 15:15
WildSery
1. По begin..end см. "savepoints", "system savepoints". Проблема явно в них.
2. Хамите, парниша? Можешь не писать - не пиши.
3. Делать можно всё. Ты явно нарвался на какой-то глюк (или "особенность") работы IB. Глюки не документируют, их исправляют. И посоветовали тебе не "совсем не делать", а "так не делать, обойти проблему".
Добавлено: 11 апр 2008, 16:21
PostMan007
Человек просил конструктивный совет, а вы выливаете ему какой-то шлак. А его "хамство" это результат на ваше хамство (см пост мерина)... и модератору, если он не слеп на один глаз, следовало бы обратить внимание и выставить предупреждение сначало на этот пост.
А проблема действительно серьезная. У меня подобное происходит тоже на ИБ7.5 и ИБ2007. Интересно есть ли такое в MSSQL?
из примерчика получается что индексы не откатываются при эксепшенах...
Выход - делать коммит после инсерта (если можно)
Добавлено: 11 апр 2008, 16:59
WildSery
PostMan007 писал(а):Человек просил конструктивный совет
И ему дали конструктивный совет - так не делать, обойти проблему.
PostMan007 писал(а):Интересно есть ли такое в MSSQL?
Кто-то из фанатов MS уже активно использует их новый, версионный, движок?
В FB, кстати, такой проблемы нет. Я уже намекнул, что похоже на баг в IB.
Добавлено: 11 апр 2008, 17:23
hvlad
PostMan007 писал(а):Выход - делать коммит после инсерта (если можно)
Нет. Делать роллбек при ошибках, а не надеяться на коммит половины тр-ции.