Умирают индексы и внешние ключи

Access Violation, некорректное выполнение запросов или вызовов API, ошибки утилит командной строки, в общем все, что вам мешает работать

Модераторы: kdv, dimitr

Enklgd01
Сообщения: 4
Зарегистрирован: 21 фев 2008, 11:00

Умирают индексы и внешние ключи

Сообщение Enklgd01 » 21 фев 2008, 12:07

InterBase 7.5.0.174

Ситуация по логике: добавляется запись, потом вызывается хранимая процедура, которая по некоторой логике эту запись разбивает на несколько (в исходной записи есть число, после разбития сумма чисел в полученных записях равно исходной). Временами возникают условия, при которой разбить на несколько записей не удается, в этом случае процедура вызывает EXCEPTION EX_NAME;

Теперь проблема: если добавить запись, сделать Commit, а потом вызвать процедуру, то просто получаю Exception.
Если добавить запись и НЕ делая Commit вызвать процедуру, то:
1) "слетают" (corrupt) все внешние ключи в этой таблице
2) слетают все индексы этой таблицы, в которых есть указание одного из полей внешних ключей
3) умирает часть внешних ключей в других таблицах (эти таблицы в процедуре используются только для SELECT)

Попытки использовать в приложении SavePoint никаких результатов не дали.
Временное решение получено: расстановка в процедуре некоторого кол-ва флагов с дополнительными SELECT'ами, но из-за этого увеличилось время выполнения процедуры.

Непонятна причина падения индексов, несмотря на то, что всё, что эта транзакция делает RollBack при получении ошибки.

При этом, обращу еще раз внимание: если сделать Commit записи, а потом начать новую транзакцию -- всё работает без повреждений базы, если транзакцию не коммитить, а пытаться провести действия сразу после добавления, то индексы умирают.

PS: для доступа в приложении используется IBX11

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 21 фев 2008, 12:48

В процедуре используются Savepoints? Их реализация в PSQL некорректна. В FB поэтому разрешены только на клиенте.

Enklgd01
Сообщения: 4
Зарегистрирован: 21 фев 2008, 11:00

Сообщение Enklgd01 » 21 фев 2008, 13:08

Merlin писал(а):В процедуре используются Savepoints? Их реализация в PSQL некорректна. В FB поэтому разрешены только на клиенте.
нет, использование SavePoint пробовалось в клиентском приложение, не в хранимой процедуре.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 21 фев 2008, 13:16

Погляди на сайте, не было ли сервис-паков для 7.5, я с IB не работаю, не помню какие версии патчились.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 21 фев 2008, 13:42

www.ibase.ru/devinfo/allversions.htm
апдейты на офсайте. Надо 7.5.1 SP 1
Если добавить запись и НЕ делая Commit вызвать процедуру, то:
1) "слетают" (corrupt) все внешние ключи в этой таблице
что-то страшное... либо какой то неизвестный ранее баг (нам не попадалось), либо стечение обстоятельств, и на машинке есть кривое железо.

Enklgd01
Сообщения: 4
Зарегистрирован: 21 фев 2008, 11:00

Сообщение Enklgd01 » 21 фев 2008, 14:19

kdv писал(а):и на машинке есть кривое железо
думалось и такое, но... проверялось на 3-х разных машинках у себя и на 2-х у других людей... в каждом тесте каждая машинка являлась сервером (они вообще никак не связаны между собой)... и везде такая ситуация...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 21 фев 2008, 15:55

значит обновлять надо.

Enklgd01
Сообщения: 4
Зарегистрирован: 21 фев 2008, 11:00

Сообщение Enklgd01 » 27 фев 2008, 10:20

проверки на 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) -- результаты точно такие же...

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 29 фев 2008, 00:59

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

Felix1978
Сообщения: 6
Зарегистрирован: 11 апр 2008, 00:33

Сообщение Felix1978 » 11 апр 2008, 01:05

Да тоже столкнулись с подобной проблемой, вложенность тут не причем.

Создаем таблицы

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 результат тотже!

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 11 апр 2008, 11:22

Felix1978 писал(а):Да тоже столкнулись с подобной проблемой
На каком сервере ?

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 11 апр 2008, 11:22

Выпрямляю руки, дёшево :)
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-операциями.

Felix1978
Сообщения: 6
Зарегистрирован: 11 апр 2008, 00:33

Сообщение Felix1978 » 11 апр 2008, 13:34

Таблица битая уже в этот момент. Дальнейшие приключения с FK могут быть следствиями, хотя может и сами по себе мальчики (С). Структуры метаданных создаются на коммите, сам Create - только протокол о намерениях То есть, перед Insert должен быть ещё один коммит. Ну и создание констрайнтов тоже следует коммитить перед DML-операциями.
Умник, проблема не в этом создай все с коммитами после каждого действия. Можешь потом подключиться снова и выполнить 3 действия результат битый ключ!

Проблема в том, что при вызове Insert->процедура на update->потом commit и все ж....
Причем в процедуре должно быть 2 update этой записи. А если сделать commit между insert и процедурой все ок!

Есть мысли у кого-нибудь?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 11 апр 2008, 13:43

Есть мысли у кого-нибудь?
1. не делать update одних и тех же записей в одной транзакции 2 или более раз
2. не писать такие процедуры, или пытаться все обрамлять begin/end или похоже
3. поумерить пыл в общении с участниками форума. Это уже предупреждение.

Felix1978
Сообщения: 6
Зарегистрирован: 11 апр 2008, 00:33

Сообщение Felix1978 » 11 апр 2008, 13:50

1. Причем тут begin end?
2. Может вообще на IB не писать?
3. Я просил конструктивный совет, что значит не делать? это явный глюк или где то есть официальная информация, что нельзя в процедуре делать 2 update одной записи?

Felix1978
Сообщения: 6
Зарегистрирован: 11 апр 2008, 00:33

Сообщение Felix1978 » 11 апр 2008, 13:54

Кстати проблема на ib 7.5. и на ib 2007.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 11 апр 2008, 15:15

1. По begin..end см. "savepoints", "system savepoints". Проблема явно в них.
2. Хамите, парниша? Можешь не писать - не пиши.
3. Делать можно всё. Ты явно нарвался на какой-то глюк (или "особенность") работы IB. Глюки не документируют, их исправляют. И посоветовали тебе не "совсем не делать", а "так не делать, обойти проблему".

PostMan007
Сообщения: 1
Зарегистрирован: 11 апр 2008, 15:54

Сообщение PostMan007 » 11 апр 2008, 16:21

Человек просил конструктивный совет, а вы выливаете ему какой-то шлак. А его "хамство" это результат на ваше хамство (см пост мерина)... и модератору, если он не слеп на один глаз, следовало бы обратить внимание и выставить предупреждение сначало на этот пост.
А проблема действительно серьезная. У меня подобное происходит тоже на ИБ7.5 и ИБ2007. Интересно есть ли такое в MSSQL?
из примерчика получается что индексы не откатываются при эксепшенах...
Выход - делать коммит после инсерта (если можно)

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 11 апр 2008, 16:59

PostMan007 писал(а):Человек просил конструктивный совет
И ему дали конструктивный совет - так не делать, обойти проблему.
PostMan007 писал(а):Интересно есть ли такое в MSSQL?
Кто-то из фанатов MS уже активно использует их новый, версионный, движок?
В FB, кстати, такой проблемы нет. Я уже намекнул, что похоже на баг в IB.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 11 апр 2008, 17:23

PostMan007 писал(а):Выход - делать коммит после инсерта (если можно)
Нет. Делать роллбек при ошибках, а не надеяться на коммит половины тр-ции.

Ответить