Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2002.07.25;
Скачать: [xml.tar.bz2];

Вниз

FK в IB6.0 - Firebird. Невозможно массовое удаление-добавление   Найти похожие ветки 

 
kaif   (2002-06-28 23:17) [0]

Имеется таблица Table1 (ID, ID2, NAME).
Имеется таблица Table2 (ID, NAME).
Имеется декларативная ссылочная целостность
alter table1 add constraint fk_table1_to_table2
foreign key(ID2) references Table2(ID).
1.Вставляем 10000 записей в Table1.
2.Выходим из приложения.
3.Соединяемся еще раз и удаляем 10000 записей из Table1.
4.Вставляем 10000 новых записей в Table1.
5.Выходим из приложения.
6.Соединяемся еще раз. Делаем любой SELECT запрос к таблице Table1.
7.Пытаемся выйти из приложения. Сервер виснет. Процессор не занят. Никакие действия с сервером (другое соединение) невозможны. Искусственное прекращение работы сервера (снять задачу) приводит к разрушению базы данных (orphan pages).
---------------------
Без foreign key такого не происходит.
Я провел сотни экспериментов. Менял сервер (IB6, Firbird). Менял параметры транзакции (snapshot, consistency, read committed). Все без толку. Описанные выше 7 шагов вешают сервер. Не завершает работу функция клиента
isc_detach_database.
Любопытно, что если подождать минут 20-30, приложение все же завершается. Однако все это время оно ничем не занято, к диску тоже обращений не происходит. Я слежу по Task Monitor NT4. То же положение и в Windows"98. Спокойно можно запускать другие приложения и работать.
Чем занят сервер?
Кто знает?
Ссылочная целостность через FK и так уже мне крови попортила достаточно. Но это уже полный беспредел...


 
kaif   (2002-06-29 15:17) [1]

Неужели никто с этим не сталкивался?
Не может такого быть...


 
Wizard_Ex   (2002-06-30 09:53) [2]

Она у тебя случаем не мусор подбирает при последнем селекте
Ж-0


 
kaif   (2002-06-30 13:40) [3]

Нет, не мусор. Я делаю запросы типа
SELECT COUNT(*) FROM TABLE1 в отдельной транзакции после commit основной. Потом уборка мусора 10тыс. строк не может занимать 20-30 мин. В худшем случае - 2 сек. И наконец, сервер не просто тормозит. Он клинит. Никакое обращение к нему из других соединений попросту не работает (виснет любое обращение). И процессор ничем не занят.
К тому же до попытки отсоединиться второй раз база работает великолепно. Никаких тормозов или еще чего подобного не замечается...
Потом, если это уборка мусора, то при чем тогда foreign key?
Повторяю, без foreign key эту ситуацию не удается воспроизвести даже на вставке 100тыс строк. А с foreign key при размере файла базы в 10М эта ситуация происходит после удаления-вставки даже 1 тыс. строк.


 
jedi   (2002-06-30 18:25) [4]

Mojet u tebea problemi s jelezom ? Potomu 4to takya situatsia v printsipe nevozmojna. Poprobuiu na drugom compiutore, ispol"zui lu4she SQL i ne delay o4eni bolishie tranzactsii hotea bi posle kajdie 100 DML operatsii delay commit.


 
kaif   (2002-06-30 19:25) [5]

>2 jedi © (30.06.02 18:25)
А почему Вы считаете, что такая ситуация невозможна?
Приведу целый ряд "невозможных" ошибок InterBase6.0:
1. При попытке создать Foreign Key на поле, являющееся в свою очередь полем, имеющим Foreign Key на другую таблицу происходит сбой в IB6.0. В Firebird Эта ошибка исправлена.
2. Если имеется еще хоть одно подключение к базе данных, создание любого Foreign Key невозможно с идиотским сообщением "Table is in use", хотя с ни с одной таблицей никто не работает (просто connect). Будем считать это идеологическим ограничением, ладно...
3. Но если имеется еще подключение к другой базе, в которой есть одноименная (!!!) таблица той, на которую я устанавливаю ссылку Foreign Key в этой базе, возникает то же самое сообщение "Table is in use", хотя это Table в другой базе in use, а не в этой. Эта ошибка присуствует и в Firebird тоже.
4. И наконец, невозможность массового удаления - добавления, о которой я пишу.
Я полностью отказываюсь с этих пор использовать FK механизм IB. Все пропишу в триггерах. Я потерял суммарно минимум 3 недели работы на всех этих интересных особенностях... Не говоря о том, что пришлось переходить на Firebird, что меня не вполне устраивало...


 
jedi   (2002-06-30 20:03) [6]

1. Neponyatno kak i za4em odno pole mojet silatsya na primary
key iz dvuh ili bolee tablits.
2. Ne sovsem verno kak vi ih sozdaiote vobshe ta kak sozdanie
vneshnevo kliu4a cac i liubogo drugo obiecta podruzumevaet
odin connect c baze ;-) (shitka) a vabshe ato destvitel"no
problema
3. Ne provereal

Ya dumaiu esli vi poprobuite delat" ta kak ya napisal vishe to problem ne budet, to est":

1. startuete tranzactsiu
2. delaete nekotoroe koli4estvo DML operatsii (nebol"shoe)
3. Commit
4. Opeat" to je samoe ;-)

V liuboi baze dannih ne recomenduiutsea delat" ogromnoe mnojestvo DML operatsii v odnoi tranzactsii naprimer v Oarcle ato zvyazanno s zaponeniem rollback segmentov 4to o4en" silno scazivatsea na proizvodidel"nosti.

P.S. S Interbase ya po4ti ne rabotal, prosto hotel predlojit" ideiu kak izbejat" vashusituatsiu, sorry esli ya vas obidel ;-)


 
kaif   (2002-06-30 23:53) [7]

>2 jedi © (30.06.02 20:03)
Что Вы! Вы меня не обидели.
Хотите я приведу кусок кода, а Вы мне скажете, много ли операций я делаю до commit?

procedure TForm1.Button1Click(Sender: TObject);
begin
Screen.Cursor := crHourGlass;
with Query do
try
if Active then Close;
with Transaction do
if Active then Commit;
if not db.Connected then db.Connected := True;

Transaction.StartTransaction;
SQL.Text := "DELETE FROM TABLE1";
ExecSQL;
Transaction.Commit;

Transaction.StartTransaction;
SQL.Text := "SELECT COUNT(*) FROM TABLE1";
Open;
Transaction.Commit;

Transaction.StartTransaction;
SQL.Text :=
"INSERT INTO TABLE1(ID,ID2,NAME)"#13+
"SELECT ID, cast(1 as integer), NAME FROM PROC1(10000)";
ExecSQL;
Transaction.Commit;

finally
Screen.Cursor := crDefault;
end;
end;

Этого достаточно. Можете сами попробовать. Я не вижу ничего криминального в этом коде. Он прекрасно работает, если нет foreign key. Как видите, я подтверждаю каждую команду с помощью commit. Я считаю, что это в высшей степени тривиальный код.
Я работаю с IB уже лет 5. И очень люблю этот сервер. Просто пока мне не приходилось делать массовых удалений и я не сталкивался с данной проблемой. Жаль, что с foreign key столько проблем...


 
jedi   (2002-07-01 00:11) [8]

Transaction.StartTransaction;
SQL.Text :=
"INSERT INTO TABLE1(ID,ID2,NAME)"#13+
"SELECT ID, cast(1 as integer), NAME FROM PROC1(10000)";
ExecSQL;
Transaction.Commit;

u vas tut proishodit insert na 10000 zapisei, poprobuite posle inserta cajdoi stroki sdelat" commit (nipsat" sql po drugomu);

Hotea na samom dele naverno takoi problemi katoruiu vi naverhu opisali ne doljno voznicat".
Edinstvennoe 4to eshe mogu poprobovat" posovetovat" tak napisat" pro bug grupe razrabot4ikov Firebird i esli ato destvitel"no bug to vozmojno oni ato delo ispraveat :).


 
Alexandr   (2002-07-01 06:48) [9]

2kaif:
1) Можно мне тестовый примерчик с этим глюком? Посмотрю и если глюка действительно в сервере, то отправлю кому следует...
2) ПОЛНОЦЕННУЮ Ссылочную целостность на триггерах создать НЕВОЗМОЖНО. Поскольку триггера выполняются в контексте транзакции, в отличие от ForeignKey.


 
kaif   (2002-07-01 12:36) [10]

>2 Alexandr © (01.07.02 06:48)
То, что Вы говорите очень важно. Неужели триггеры выполняются в контексте транзакции? Мне тут на форуме попадалась иная точка зрения и, честно говоря, я принял это за чистую монету. Я еще взгляну в документации по IB, но, насколько я помню, там об этом подробно не пишется...
Ваше предложение отправить кому следует меня сильно заинтересовало, так как я сам никак не возьму в толк, как связаться с ребятами из проекта Firebird... Если не возражаете, я прямо сейчас кину Вам на ящик тестовый пример.
Кстати, я попробовал Yaffils. В нем ошибка та же, но проявляется иначе. Приложение немного виснет при дисконнекте (секунд 20), а потом вылетает с сообщением Windows "Программа выполнила недопустимую операцию...". Сам Yaffils мне как-то не понравился - у меня резко (раза в 3) стало медленнее все работать. Не знаю... Просто у меня очень сложный проект и экспериментировать времени нет. Я уже остановился на Firebird. В целом он меня очень устраивает...


 
Alexandr   (2002-07-01 12:44) [11]

2kaif:
1) Жду мыло...
2) триггеры выполняются в контексте транзакции. Это естественно как коже, что солце встает на востоке, а заходит на западе...
И все другие мнения неправильные.
3)нИЧЕго сложного в общении с разработчиками Firebird, а уж тем более с разработчиками Yaffil нет. Нужна просто достаточная квалификация, чтоб они не подумали, что ты глупый ламер.




 
Alexandr   (2002-07-01 13:04) [12]

чего-то письма до сих пор нема...


 
kaif   (2002-07-01 13:10) [13]

Вроде отправил. Если пример нужно доработать (сделать диалог подключения к базе) - скажите. Это тот код, с помощью которого я сам разбирался. Если убрать FK (drop constraint...), то можно сколько угодно раз нажимать кнопку Insert-Update. Если же FK присуствует, то после нескольких таких сеансов возникнут проблемы с отсоединением от базы после SELECT. Любопытно, что если сделать Validity Check перед этим SELECT, то сервер скажет, что база в полном порядке.


 
kaif   (2002-07-01 13:25) [14]

Я тут копаюсь в литературе и шевелю мозгой. Я так думаю: если в триггере возможен SQL-запрос (а он возможен!), следовательно, триггер исполняется в контексте транзакции. Логически иначе быть не может. Хотя я уже давно стал эмпириком. Можно, впрочем проверить...
Что же теперь делать?...
Я не знаю. Последняя надежда, что у меня с железом что-то не то. Хотя вряд ли... Причем тут железо?
А делать проверку ссылочной целостности в контексте транзакции - все равно, что делать ее вообще со стороны клиента. Или даже хуже... С клиента я могу хотя бы стартовать свежую транзакцию. А до триггера данные могут сильно устареть...


 
kaif   (2002-07-01 13:27) [15]

>2Alexandr
Ну как, доставилось мыло или еще нет?


 
Alexandr   (2002-07-01 13:47) [16]

1) Мыло дошло.
2) Я по мылу ответ написал. Пора переходить общаться в мыло.
3) Программа работает.
4) Щас пытаюсь ее повесить... пока попытки неуспешны. :)
5) Я чтоб программу не перегружать просто кнопку сделал с кодом
db.Connected:=False;
db.Connected:=true;

кстати проверяю я на Yaffil Classic Server 819 сборки.
Щас еще на Firebird попробую...



 
kaif   (2002-07-01 14:07) [17]

Странно. Я тоже добавил кнопку db.Connected := False. После уже второго нажатия Insert-Update у меня на дисконнекте все повисло. Сервер Firebird-1.0.0.796-Win32.exe (стоит как суперсервер, по моему).
Письма пока не получил. Пишите мне пожалуйста на ashot@vallex.ru. Остальные ящики сейчас у меня недоступны.


 
Alexandr   (2002-07-01 14:09) [18]

1) Мыло дошло.
2) Я по мылу ответ написал. Пора переходить общаться в мыло.
3) Программа работает.
4) Щас пытаюсь ее повесить... пока попытки неуспешны. :)
5) Я чтоб программу не перегружать просто кнопку сделал с кодом
db.Connected:=False;
db.Connected:=true;

кстати проверяю я на Yaffil Classic Server 819 сборки.
Щас еще на Firebird попробую...



 
kaif   (2002-07-01 14:12) [19]

Я пробовал на Yaffil 809 (по-моему, тоже Superserver)


 
kaif   (2002-07-01 14:20) [20]

У меня такое впечатление, что ошибка не возникает, если есть еще хоть одно соединение с той же базой.
Отключите все соединения с сервером и попробуйте еще раз.


 
Alexandr   (2002-07-01 14:38) [21]

ОК.
Действительно проблема с последним отключающимся от базы.
И действительно такая бага имеет место быть - т.е. последний всегда долго отключается из-за сборки мусора.
И бага эта известна, но не помню я исправили ее или нашли как ее обойти.

Другое дело, что уж очень долго последний отключается...



Остальное завтра.


 
kaif   (2002-07-01 15:06) [22]

2Alexandr ©
Спасибо за помощь. До завтра.


 
Alexandr   (2002-07-02 06:32) [23]

сдается мне, дело в параметре транзакции
read-write table stability
если поставить чего попроще (я пробовал read Commited) то все нормально... вроде бы.


 
kaif   (2002-07-02 13:50) [24]

>2 Alexandr © (02.07.02 06:32)
Я начинал эксперименты с Read Committed. Именно тогда проявилась эта ошибка. Это уже потом я играл с транзакциями. Но безуспешно. Вопрос в том, что это не уборка мусора, так как при этом невозможно новое подключение к серверу и процессор ничем не занят. Такое впечатление, что сервер попадает в какой-то тупик на "счетчике подключений" и просто чего-то ждет на функции вроде WaitForSingleObject... или что-то в этом духе.


 
Alexandr   (2002-07-02 13:58) [25]

А что, у тебя и на ReadCommited такое появляется?



 
kaif   (2002-07-02 14:26) [26]

Да. Я только что проверил еще раз, перекомпилировав с ReadCommitted.
1. Восстановил пустую базу из *.gbk
2. Отключил IBConsole.
3. Нажал Insert-Update 10000.
4. Нажал Select
5. Нажал Disconnect
6. Нажал Insert-Update 10000.
7. Нажал Select
8. Нажал Disconnect
9. Провисел 3 мин.///////////////////
10. Нажал Insert-Update 10000.
11. Нажал Select
12. Нажал Disconnect
13. Вот уже висю 5 мин.//////////////////


 
kaif   (2002-07-02 14:37) [27]

Я пишу приложение на рынок (альтернатива 1С). Я очень опасаюсь за сохранность базы. Очнь вероятно, что пользователь, увидев, повисшее даже на 2 мин. приложение, просто убьет его с помощью Ctrl+Alt+Del. После этого сервер работать не будет. Придется и его убить так же. Потом стартовать. Восстановление базы с 200 orphan pages не получается без отключения ignore check sum. После такого восстановления индексы получаются неправильные и многое выпадает. Нужно восстанавливать индексы. В большинстве случаев базу просто приходится выкинуть.
А расчет с удалением-вставкой тысяч строк вполне обычное дело при перерасчете себестоимости списанных товаро и других подобных задачах.
Одним словом это хана.
Мне нужно найти какой-то надежный выход.
Кстати, висю уже 7 мин.//////////
Я уже убрал всю ссылочную целостность из базы и из программы в тех местах, гда она создавалась.
Я готов все это восстановить, если найду решение.
Иначе придется ее поддерживать руками в отдельных транзакциях с клиента.
----------
Неужели у тебя не происходит зависания на ReadCommitted?
Может мне опять менять сервер?


 
kaif   (2002-07-02 14:51) [28]

После третьего Insert-Update (помните?)
висю уже 17 минут.


 
Alexandr   (2002-07-03 06:42) [29]

в мыло!


 
Alexandr   (2002-07-03 07:09) [30]

Yaffil SS 819

все работает и ничего нигде не виснет проверено.

Firebird 682

зависания продолжаются...

Юзайте Yaffil, господа и волосы станут мягкими и шелковистыми


 
kaif   (2002-07-03 12:40) [31]

Хорошо. Попробую сегодня скачать Yaffil SS 819. Но как его ставить? Я последний раз поставил Yaffil на голову Interbase. Просто скопировал файлы сервера и gds32.dll кинул в System32 (у меня NT4). Но получил значительное падение скорости плюс какие-то ошибки. Как правильно его ставить? Есть тонкости?


 
kaif   (2002-07-03 12:45) [32]

Alexandr, простите
а в чем разница между RC2 и RC3?
Там в download:
Сборки WIN32 (суперсервер)
RC3 (821) 1.5 Мб
RC2 (800) 1.5 Мб


 
kaif   (2002-07-03 12:48) [33]

Там еще написано
НЕ ЗАБЫВАЙТЕ ОБНОВЛЯТЬ intl\gdsintl.dll

А как используется этот файл и кем?


 
kaif   (2002-07-03 20:12) [34]

Поставил Yaffilss821.
Все работает идеально.
Вопрос снят.


 
Alexandr   (2002-07-04 06:37) [35]

ну раз вопрос снят, то я уже отвечать не буду...



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2002.07.25;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.007 c
1-81266
Gala
2002-07-14 12:27
2002.07.25
отмена выделения текста в ячейке DBgrid


1-81288
ctapik-net
2002-07-12 07:37
2002.07.25
Локализация приложения под другие языки.


14-81465
mifi
2002-06-28 09:27
2002.07.25
Openfile в скрипте


6-81394
chernoruk
2002-05-13 07:53
2002.07.25
Последний раз про IP и GetHostByName


1-81356
Klon
2002-07-13 16:37
2002.07.25
Как рисовать в чужом окне или по всему экрану?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский