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

Вниз

Неясна причина ошибки   Найти похожие ветки 

 
tech ©   (2006-01-12 23:16) [0]

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

"Too many concurrent executions of the same request"

Перегрузка программы ситуацию не исправляет, запрос не работает сразу-же, уже при первом обращении.

В то же время и в загруженном IBExpert, и в перезагруженном, этот же запрос исполняется без проблем.

В чем проблема? Как разгрести ситуацию?


 
Bogdan1024 ©   (2006-01-13 00:11) [1]

База ругается потому что ей дали два одинаковых запроса? Ух и тупая база :)


 
Johnmen ©   (2006-01-13 09:49) [2]

Ошибка известная. Приводи текст запросов.


 
tech ©   (2006-01-13 15:42) [3]

Вот текст запроса

select name, 1
from CON_DEF(:doc,:def,:def_,null) where def=:con
union
select name, 2
from CON_DEF(:doc,:def,:def_,:con)
where def=:con_ and def <>0
order by 2


поднимается группа объектов первого уровня, из них отбирается тот, что имеет def=:con, его имя подается наверх (первая часть);

поднимается группа объектов второго уровня, подчиненного :con, из них отбирается тот, что имеет def=:con_, его имя подается наверх (вторая часть),
если у второго объекта def =0, то его имя не поднимается;

В программе по результатам запроса строится адрес вида: "Первый объект" или "Первый объект"."Подчиненный объект".

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


 
Johnmen ©   (2006-01-13 15:44) [4]

Теперь приводи текст ХП CON_DEF.


 
tech ©   (2006-01-13 15:55) [5]

Просили? получите.

CREATE PROCEDURE CON_DEF (
   CC INTEGER,
   DF INTEGER,
   DF_ INTEGER,
   CF INTEGER)
RETURNS (
   ORD INTEGER,
   DOC_ INTEGER,
   DEF INTEGER,
   NAME VARCHAR(47),
   OK CHAR(2))
AS
DECLARE VARIABLE CN INTEGER; /* тип коннектора */
DECLARE VARIABLE AF INTEGER; /* тип связи */
BEGIN
/* CF деф - деф подстановки, если нул то выдаются дефы класса, иначе дефы подстановки.
  ОК  TT-можно соединять и есть кандидаты уровнем ниже
      TF-можно соединнять уровнем ниже кандидатов нет
      FT-соединнять нельзя но есть кандитдаты уровнем тиже */

/* определим тип коннектора */
 select doc from def_type(:cc,:df,:df_)into:cn;
 if (cn not in(31,32)) then exception PARAM_IS_BAD "con_def: данный деф не является коннектором.";

 /* определим тип связи он эквивалентен типу подложки коннектора */
 if (df_=0) then df_=null; /* искусственно будем считать что надо анализировать деф класса */
 select doc from loc_type(:cc,:df,:df_)into :af;

 /* определим, что нужно выдать, дефы класса, или дефы дефа */
 if (cf is not null) then begin
   select doc_ ," " from def_up(:cc,:cf,0) into :cc,:ok;--ok используется как индикатор исп. запроса
   if (ok is null) then exception PARAM_IS_BAD "con_def: ид d"||:cc||" f"||:cf||" не существует.";
 end

 /* перебор всех дефов класса и их маркирование в зависимости от уровня вложености и пригодности к соединению  */
 for select def ,name ,ord ,doc_ from doc_def(:cc) into :def,:name,:ord,:doc_ do begin

   -- проверка на пригодность к соединению.
   if (exists(select * from def_type(:cc,:def,0) where doc=:af)) then ok="TF";else ok="FF";

   -- если перебираем дефы нулевого уровня вложенности, проверим кандитатов уровнем ниже
   if (cf is null) then begin

     select doc_ from def_up(:cc,:def,0) into :doc_;-- найдем класс подстановки
     if( exists(select * from doc_def(:doc_)d where
         exists(select * from def_type(:doc_,d.def,0) where doc=:af)))
       then if (ok="TF") then ok="TT"; else ok="FT";
   end

   if (ok in ("TT","TF","FT")) then suspend;
 end
END


 
Johnmen ©   (2006-01-13 16:07) [6]

Теперь приводи тексты всех вызываемых ХП.
Шутка! :)

Замечание такое
После поднятия ексепшна выполнение прекращается, некот.вых параметры не проинициализированы, да и до саспенда дело не доходит...
Ещё стОит обратить внимание на возможную бесконечную рекурсию.
Кстати, а в этих процедурах нет ли модифицирующих запросов?


 
tech ©   (2006-01-13 16:40) [7]

...нет ли модифицирующих запросов?...

Совершенно точно нет. Только селекты.

...бесконечную рекурсию...

Как это проверить? Никакой задержки на глаз не видно.

...поднятия ексепшна...

Напомню вопрос. Ексепшн происходит совсем в другом месте, при попытке записи данных в некую таблицу, к которой данная процедура ни прямо, ни через другие процедуры не обращается (проверил по зависимостям). ПОСЛЕ этого эксепшена перестает работать приведенный запрос, а все прочие запросы в системе продолжают исполняться как ни в чем не бывало (а их больше сотни, и часть их обращаются к таблице, при записи в которую возник ексепшн).

Я не понимаю, как можно запросами, пусть и неправильными, поставить FireBird таким раком, чтобы и после перезагрузки программы тут же возникала эта ошибка!


 
Johnmen ©   (2006-01-13 23:05) [8]

> Ексепшн происходит совсем в другом месте, при попытке записи данных в некую таблицу

Вот здесь поподробнее. Что за место, какая попытка.


 
tech ©   (2006-01-13 23:41) [9]

Запись происходит в таблицу "коммутации", в ней пять integer полей: doc,def,def_,com,com_. Пары def,def_ - com,com_ собственно образуют коммутацию, принадлежащую объекту doc.
При записи выполняется проверка допустимости коммутации двумя чеками, один из которых проверяет наличие самих комутируемых объектов, второй -совпадение типов соединения. В случае попытки записи негодных данных либо генерится ексепшн либо срабатывает сам чек.
тексты чеков:

exists(select * from con_check(dmf.doc,dmf.def,dmf.def_,dmf.com,dmf.com_))
exists(select * from def_type(dmf.doc,dmf.def,dmf.def_) where doc in (31,32))


и процедур

CREATE PROCEDURE CON_CHECK (
   CC INTEGER,
   DF INTEGER,
   DF_ INTEGER,
   CM INTEGER,
   CM_ INTEGER)
RETURNS (
   OK CHAR(1))
AS
DECLARE VARIABLE CN INTEGER; /* тип коннектора */
DECLARE VARIABLE AF INTEGER; /* тип активного  дефа суть тип подложки коннектора */
DECLARE VARIABLE PF INTEGER; /* тип пассивного дефа суть тип дефа предмета связи */
BEGIN

 /* определим тип коннектора */
 select doc from def_type(:cc,:df,:df_)into:cn;
 if (cn not in(31,32)) then exception PARAM_IS_BAD "con_type: данный деф не является коннектором.";
 /* определим тип пассивного дефа*/
 select doc from def_type(:cc,:cm,:cm_)into:pf;

 /* определим тип подложки коннектора */
 if (df_=0) then df_=null; /* искусственно будем считать что надо анализировать деф класса */
 select doc from loc_type(:cc,:df,:df_)into :af;

 /* проверим допустимость связи */
 if(:cn=31)/* коннектор get типа */ then select "T" from doc_up(:pf )where doc=:af into:ok;
 if(:cn=32)/* коннектор put типа */ then select "T" from doc_up(:af )where doc=:pf into:ok;
 if(ok is not null)then suspend;

END

CREATE PROCEDURE DEF_TYPE (
   CC INTEGER,
   DF INTEGER,
   DF_ INTEGER)
RETURNS (
   DOC INTEGER,
   DEF INTEGER,
   DEF_ INTEGER)
AS
BEGIN
/* Базовая процедура модели.
  хх.хх.2002г. работет правильно с ветвлением ссылок.
  сейчас ветвление ссылок просто игнорируется.
  06.02.2002г. написана
  21.02.2002г. работет правильно со значениями
  18.03.2002г. работет правильно со ссылками
  11.01.2006u. работает с типами "коннектор"

Если входной параметр df_ определен (не null), возвращает тип дефа.
Если класс подстановки данного дефа определен (is not null) то тип дефа
определяется как класс подстановки, нулевого (ассоциативного) слоя его подстановки.
Если класс подстановки данного дефа не определен (is null), значит данный деф
суть ссылка на более глубокий деф его подложки. В этом случае тип
дефа суть тип дефа на который он указывает.

Если входной параметр df_ не опеределен (is null), возвращает класс подстановки.

Возвращает тип дефа, если df_ null или тип значения, если df- определен.
Тип дефа интересен, когда необходимо узнать тип ссылки.
*/
 /* проверим существование дефа у данного класса  и заодно извлечем его атрибуты*/
 select doc_,loc,def_ from def_up(:cc,:df,0)into:doc,:def,:def_;
 /* такая ситуация может быть только в случае, если заданный док.деф не обнаружен*/
 if (doc is null and def is null) then
   exception DEF_IS_NOT_FOUND1 "def_type: ид d_"||:cc||" f_"||:df||" не существует.";

 /* требуется просто вернуть класс подстановки данного дефа (df_ is null)*/
 if (doc is not null and df_ is null) then begin suspend; exit; end

 /* Если тип дефа определен, снова проверим существование дефа (df_)
 и выдадим его в качеве искомого типа (doc).
 Если тип дефа не определен, значит это ссылка. Сделаем переход по
 ссылке и уйдем на рекурсию.*/
 if (doc is not null)
 then begin /*выход из проц.*/
   cc=null;/*только для проверки исполнения запроса */
   select doc_,doc from def_up(:doc,:df_,0)into:doc,:cc;
   if (cc is null ) then exception DEF_IS_NOT_FOUND2; else suspend; end
   
 else begin/* уход на рекурсию */
   select doc_ ,loc from def_up(:cc ,:def,0)into:doc,:def;
   if (def is null) then exception zz3;/* ветвление ссылки */
   select doc,def,def_ from def_type(:doc,:def_,:df_)into :doc,:def,:def_;
   suspend;
 end

END


Я намеренно или ненамеренно пытаюсь записать в таблицу неправильные данные и вполне справедливо получаю отлуп. Вот после этого отлупа упомянутый в начале переписки запрос и перестает выполняться. Останавливаю программу, запускаю ее снова и сразу же имею "Too many concurrent... при попытке выполнить запрос на чтение адреса комутации. Данные при этом в базе лежат только правильные. Том же запрос на IBExpert выполняется на ура.


 
Johnmen ©   (2006-01-13 23:53) [10]

>Я намеренно или ненамеренно пытаюсь записать в таблицу неправильные данные и вполне справедливо получаю отлуп.

Вот это я и просил поподробней, насчёт попытки записи. Где, как, чем...


 
tech ©   (2006-01-14 00:01) [11]

Есть специальная процедура для записи значений разных типов, для Вас инресен последний ее кусок, где типы 31,32

CREATE PROCEDURE VAL_WRITE (
   CC INTEGER,
   DF INTEGER,
   DF_ INTEGER,
   TP INTEGER,
   STR VARCHAR(255),
   QNT NUMERIC(18,4),
   DT TIMESTAMP,
   RD INTEGER,
   COM INTEGER,
   COM_ INTEGER,
   MEM BLOB SUB_TYPE 1 SEGMENT SIZE 100)
RETURNS (
   OK CHAR(2))
AS
BEGIN
/* 31.01.2002г.
 Записывает значение дефа.
 26.02.2002г. редакция - добавлена ссылка
 10.12.2005г. редакция И.К. - добавлен базовый тип - "класс"
 28.12.2005г. редакция И.К. - добавлен базовый тип - "коммутация"
*/
/* запись строки */
 if (:tp=3) then begin
   if (exists(select * from dms   where doc=:cc and def=:df and def_=:df_))
   then begin
     if (:str is null)
     then begin delete from dms         where doc=:cc and def=:df and def_=:df_; ok="sd";end
     else begin update dms set str=:str where doc=:cc and def=:df and def_=:df_; ok="su";end end
   else if (:str is not null) then begin
        insert into dms values (:cc,:df,:df_,:str); ok="si";end
   suspend; exit; end else
/* запись числа   */
 if (:tp=4) then begin
   if (exists(select * from dmc   where doc=:cc and def=:df and def_=:df_))
   then begin
     if (:qnt is null)
     then begin delete from dmc         where doc=:cc and def=:df and def_=:df_; ok="cd";end
     else begin update dmc set qnt=:qnt where doc=:cc and def=:df and def_=:df_; ok="cu";end end
   else if (:qnt is not null) then begin
        insert into dmc values (:cc,:df,:df_,:qnt); ok="ci";end
 suspend; exit; end else
/* запись даты */
 if (:tp=5) then begin
   if (exists(select * from dmd   where doc=:cc and def=:df and def_=:df_))
   then begin
     if (:dt is null)
     then begin delete from dmd         where doc=:cc and def=:df and def_=:df_; ok="dd";end
     else begin update dmd set  dt=:dt  where doc=:cc and def=:df and def_=:df_; ok="du";end end
   else if (:dt is not null) then begin
        insert into dmd values (:cc,:df,:df_,:dt ); ok="di";end
   suspend; exit; end else
/* запись blob */
 if (:tp=6) then begin
   if (exists(select * from dmb   where doc=:cc and def=:df and def_=:df_))
   then begin
     if (:mem is null)
     then begin delete from dmb         where doc=:cc and def=:df and def_=:df_; ok="bd";end
     else begin update dmb set mem=:mem where doc=:cc and def=:df and def_=:df_; ok="bu";end end
   else if (:mem is not null) then begin
        insert into dmb values (:cc,:df,:df_,:mem );  ok="bi";end
   suspend; exit; end else
 /* запись ссылки */
 if (:tp=7) then begin
   if (exists(select * from dmr   where doc=:cc and def=:df and def_=:df_))
   then begin
     if (:rd is null)
     then begin delete from dmr         where doc=:cc and def=:df and def_=:df_; ok="rd";end
     else begin update dmr set  rd=:rd  where doc=:cc and def=:df and def_=:df_; ok="ru";end end
   else if (:rd is not null) then begin
        insert into dmr values (:cc,:df,:df_,:rd ); ok="ri";end
   suspend; exit; end else  
 /* запись класса */
 if (:tp=8) then begin
   if (exists(select * from dmo   where doc=:cc and def=:df and def_=:df_))
   then begin
     if (:rd is null)
     then begin delete from dmo         where doc=:cc and def=:df and def_=:df_; ok="od";end
     else begin update dmo set  rd=:rd  where doc=:cc and def=:df and def_=:df_; ok="ou";end end
   else if (:rd is not null) then begin
        insert into dmo values (:cc,:df,:df_,:rd ); ok="oi";end
   suspend; exit; end else  
 /* запись коммутации */
 if (:tp in (31,32)) then begin
   if (exists(select * from dmf   where doc=:cc and def=:df and def_=:df_))
   then begin
     if (:com is null)
     then begin delete from dmf         where doc=:cc and def=:df and def_=:df_; ok="fd";end
     else begin update dmf set com=:com,com_=:com_ where doc=:cc and def=:df and def_=:df_; ok="fu";end end
   else if (:com is not null) then begin
        insert into dmf values (:cc,:df,:df_,:com,:com_ ); ok="fi";end
   suspend; exit; end  
END


особенность такова, что "пустых" значений не бывает (у нас), поэтому есть и удаление.


 
Johnmen ©   (2006-01-14 00:07) [12]

Так...
А есть ли триггеры на модифицируемые таблицы?
Откуда вызывается данная процедура?


 
tech ©   (2006-01-14 00:13) [13]

На таблицу dmf только один триггер, запрещающий удалять две строки:

if (old.doc in (31,32) and old.def=0 and old.def_=0) then exception obj_protection;

второй триггер, запрещающий модифицировать эти же строки пока отключен (надо бы включить, но пока отладка).


 
Johnmen ©   (2006-01-14 00:18) [14]

Отключи и этот триггер.
И попробуй заново получить сабжевую ошибку.


 
tech ©   (2006-01-14 00:19) [15]

Что-то я прихожу к выводу, что на самом деле некорректная запись, которая была отвергнута чеками, почему-то осталась в базе в рамках выполняемой транзакйии (потому ее и не видно из IBExpert). Но вот как это может быть? Ведь по любому ексепшену длжен происходить откат.


 
Johnmen ©   (2006-01-14 00:27) [16]

По ексепшну не происходит отката транзакции, а только лишь прерывание выполнения процедуры/триггера.


 
tech ©   (2006-01-14 00:56) [17]

Отключил все триггеры. При попытке записать неверные данные срабатывает ексепшен "неверный деф подстановки" - как и должно было быть. Затем все то-же самое "Too many...".
Но, некоторое уточнение, почему-то в отладочном режиме дельфи первым вываливается "Too many... раза два, потом доходит ексепшен "неверный деф подстановки", потом опять "Too many... непрерывно при каждом обращении.


 
tech ©   (2006-01-14 01:43) [18]

...По ексепшну не происходит отката транзакции...

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

Получается, что я программно должен ловить ексепшены базы и принудительно откатывать транзакции? А как же все работало до сих пор, я ведь ничего сам, ручками, не откатывал, хотя ексепшенов за 6 лет разработки была гора и маленькая тележка? Не понимаю.
Ну ладно, пойду спать, уже почти 5 часов утра. Большое спасибо за участие. Буду рад, если Вы меня немного просвятите по поводу моего непонимания.



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

Форум: "Начинающим";
Текущий архив: 2006.01.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.048 c
15-1136806914
psa247
2006-01-09 14:41
2006.01.29
Кодировка ?


2-1136988441
RDS
2006-01-11 17:07
2006.01.29
процессы


2-1136911291
HITMAN1
2006-01-10 19:41
2006.01.29
Где можно найти информацию о значениях портов


2-1136634468
Nic
2006-01-07 14:47
2006.01.29
Как закрыть программу в C#


4-1132430885
Serafim-s
2005-11-19 23:08
2006.01.29
Передача файлов по RS232





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский