powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / AQ и подписчики
16 сообщений из 16, страница 1 из 1
AQ и подписчики
    #39230107
rybingleb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Сделал очередь, зарегистрировал подписчика и plsql метод, который автоматически вызывается при добавлении сообщения в очередь. Все хорошо.
Теперь есть задача временно прекратить разбор сообщений на какое-то время и потом его продолжить. Как это сделать?
Если остановить dequeue очереди через
Код: plsql
1.
2.
3.
begin
  dbms_aqadm.stop_queue(queue_name => 'XXTEST_QUEUE', dequeue => true);
end;


, то как потом сделать, чтобы сообщения, которые накопились в очереди, разобрались подписчиком? Новые сообщения разбираются, а те, что уже есть, так и лежат в очереди.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230366
rybinglebСделал очередь, зарегистрировал подписчика и plsql метод, который автоматически вызывается при добавлении сообщения в очередь. Все хорошо.
Теперь есть задача временно прекратить разбор сообщений на какое-то время и потом его продолжить. Как это сделать?
Если остановить dequeue очереди через
Код: plsql
1.
2.
3.
begin
  dbms_aqadm.stop_queue(queue_name => 'XXTEST_QUEUE', dequeue => true);
end;


, то как потом сделать, чтобы сообщения, которые накопились в очереди, разобрались подписчиком? Новые сообщения разбираются, а те, что уже есть, так и лежат в очереди.

Не знаю какая у вас версия , я на 9-й проходил
когда распухает q-table начинаются дикие тормоза
на HWM и тд итп .

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

Вобщем выпилили эту фичу из бизнес процессов и возвращаться
желания нет.

Если очередь имеет свойство накаплшиваться , рекомендую более
углубленно протестировать производительность в разных режимах накопления.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230452
HX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>, то как потом сделать, чтобы сообщения, которые накопились в очереди, разобрались подписчиком? Новые сообщения разбираются, а те, что уже есть, так и лежат в очереди.
Можете приложить тесткейз (полные скрипты для репродуцирования) текст plsql notification,если он конфиденциален, можно не публиковать.
При всем, попробуйте предоставить сценарий, которой худо-бедно можно будет повторить в базе данных не имеющей отношения к Вашей application specific.

Поясню цель: при наличии тесткейза понимание сути данной проблемы инженерами со стороны и ее последующее решение значительно ускорится.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230461
ma1tus
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rybingleb...
, то как потом сделать, чтобы сообщения, которые накопились в очереди, разобрались подписчиком? Новые сообщения разбираются, а те, что уже есть, так и лежат в очереди.
Нотификация - доп. фишка, для основного режима на клиентской стороне д.б. прямое вычитывание...
Вычитать и вчитать обратно - не помогло?
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230537
de'Queue
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rybinglebсделать, чтобы сообщения, которые накопились в очереди, разобрались подписчиком?вызывать в цикле подписанную процедуру обработки, пока есть сообщения.
Для поддержки временной приостановки удобнее повесить джоб(ы) и в них заложить реакцию на stop dequeue или, если кроме них никто не читает, просто останавливать джобы.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230562
rybingleb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
de'Queuerybinglebсделать, чтобы сообщения, которые накопились в очереди, разобрались подписчиком?вызывать в цикле подписанную процедуру обработки, пока есть сообщения.
Для поддержки временной приостановки удобнее повесить джоб(ы) и в них заложить реакцию на stop dequeue или, если кроме них никто не читает, просто останавливать джобы.

Вот как раз хотелось уйти от джобов. Сейчас так и сделано - есть очередь, есть джоб, который постоянно запускает процедуру, которая делает dequeue. Мне это казалось немного костыльным.

авторМожете приложить тесткейз (полные скрипты для репродуцирования) текст plsql notification,если он конфиденциален, можно не публиковать.
При всем, попробуйте предоставить сценарий, которой худо-бедно можно будет повторить в базе данных не имеющей отношения к Вашей application specific.

Поясню цель: при наличии тесткейза понимание сути данной проблемы инженерами со стороны и ее последующее решение значительно ускорится.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
/*создать тип*/
create Type message_typ as object ( 
  subject Varchar2(30), text Varchar2(80)
);

/*создать таблицу для очереди, очередь, запустить очередь*/
begin
  dbms_aqadm.create_queue_table( 
    queue_table        => 'XXTEST_QUEUE_TAB',
    queue_payload_type => 'MESSAGE_TYP',
    multiple_consumers => true);

  dbms_aqadm.create_queue(
    queue_name  => 'XXTEST_QUEUE',
    queue_table => 'XXTEST_QUEUE_TAB'); 

  dbms_aqadm.start_queue(
    queue_name => 'XXTEST_QUEUE');
end;

/*создать процедуру для добавления в очередь*/
create or replace procedure enqueue_msg( p_msg in varchar2 )
as
  enqueue_options    dbms_aq.enqueue_options_t;
  message_properties dbms_aq.message_properties_t;
  message_handle     RAW(16);
  message            message_typ;
begin

   message := message_typ('NORMAL MESSAGE',  p_msg );

   dbms_aq.enqueue(queue_name => 'XXTEST_QUEUE',
                   enqueue_options    => enqueue_options,
                   message_properties => message_properties,
                   payload            => message,
                   msgid              => message_handle);
end;

/*создать талицу, куда будут писаться сообщения из очереди*/
create table message_table( 
   msg           varchar2(4000)
  ,creation_date date
  ,info          varchar2(150)
);

/*создать процедуру для обработки сообщения из очереди*/
create or replace procedure XXTEST_CALLBACK( context raw,
                                      reginfo sys.aq$_reg_info,
                                      descr sys.aq$_descriptor,
                                      payload raw,
                                      payloadl number)
as
  dequeue_options    dbms_aq.dequeue_options_t;
  message_properties dbms_aq.message_properties_t;
  message_handle     raw(16);
  message            message_typ;
begin
  xxfnd_log_pkg.log(i_api_name => 'XXTEST_CALLBACK', i_msg => 'start', i_at => true);
  
  dequeue_options.msgid         := descr.msg_id;
  dequeue_options.consumer_name := descr.consumer_name;

  DBMS_AQ.DEQUEUE(
    queue_name         => descr.queue_name,
    dequeue_options    => dequeue_options,
    message_properties => message_properties,
    payload            => message,
    msgid              => message_handle);

  insert into message_table(msg, creation_date, info)
  values('Dequeued and processed "' || message.text || '"', sysdate, sys_context('USERENV', 'SID'));
  
  dbms_lock.sleep(1); --!!!

  commit;
exception
  when others then
    xxfnd_error.eh('XXTEST_CALLBACK');
end XXTEST_CALLBACK;

/*создать подписчика*/
begin
  dbms_aqadm.add_subscriber( 
    queue_name => 'XXTEST_QUEUE',
    subscriber =>  sys.aq$_agent('XXSUBSCRIBER', null, null));
end;

/*Регистрация листенера*/
DECLARE
 reginfo1     sys.aq$_reg_info;
 reginfolist  sys.aq$_reg_info_list;
BEGIN
 reginfo1 := sys.aq$_reg_info('INFONEXT.XXTEST_QUEUE:XXSUBSCRIBER',
                    DBMS_AQ.NAMESPACE_AQ,
                    'plsql://XXTEST_CALLBACK',
                    HEXTORAW('FF'));
 
 -- Create the registration info list
 reginfolist := sys.aq$_reg_info_list(reginfo1);
 
 -- do the registration
 sys.dbms_aq.register(reginfolist, 1);
END;

/*добавление множества сообщений*/
begin
  for r in 1..1000 loop
    enqueue_msg('test'||to_char(r));
  end loop;
end;

commit;



Все работает нормально, очередь разгребается, по-моему, в пять потоков, сообщения переносятся в таблицу message_table. К примеру, у меня таким образом будут рассылаться СМС. Допустим, я нашел ошибку в процедуре XXTEST_CALLBACK и хочу временно остановить разбор очереди, но при этом не останавливать добавление сообщений в очередь.
Делаю
Код: plsql
1.
2.
3.
begin
  dbms_aqadm.stop_queue(queue_name => 'XXTEST_QUEUE', enqueue => false, dequeue => true);
end;


Смотрю
Код: plsql
1.
2.
select * from all_queues q
where q.name = 'XXTEST_QUEUE';


Все ок, ENQUEUE_ENABLED = YES, DEQUEUE_ENABLED = NO. Очередь перестает разбираться, процедура XXTEST_CALLBACK пишет ошибки "ORA-25226: dequeue failed, queue INFONEXT.XXTEST_QUEUE is not enabled for dequeue".
Все как я и хотел.
Потом, допустим, я исправил ошибку в процедуре XXTEST_CALLBACK. И хочу продолжить разбор очереди. Делаю
Код: plsql
1.
2.
3.
begin
  dbms_aqadm.start_queue(queue_name => 'XXTEST_QUEUE');
end;


В результате сообщения, которые были в очереди после остановки, так там и остаются. Вот как теперь сделать, чтобы процедура XXTEST_CALLBACK продолжила их разбирать.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230712
В данном случае, наверное, нужно остановить enque, дождаться пока все сообщения разберуться агентом, и после этого останавливать dequeue, если нужно.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230828
HX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я бы сделал перед остановкой очереди сначала unregister:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
DECLARE
 reginfo1     sys.aq$_reg_info;
 reginfolist  sys.aq$_reg_info_list;
BEGIN
 reginfo1 := sys.aq$_reg_info('XXTEST_QUEUE:XXSUBSCRIBER',
                    DBMS_AQ.NAMESPACE_AQ,
                    'plsql://XXTEST_CALLBACK',
                    HEXTORAW('FF'));
 
 -- Create the registration info list
 reginfolist := sys.aq$_reg_info_list(reginfo1);
 
 -- do the registration
 sys.dbms_aq.unregister(reginfolist, 1); 
END;


потом остановил очередь, сделал изменения в процедуре, потом запустил очередь, потом снова sys.dbms_aq.register.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230900
rybingleb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Попробуйте такВ данном случае, наверное, нужно остановить enque, дождаться пока все сообщения разберуться агентом, и после этого останавливать dequeue, если нужно.
Если остановить enque, то все процессы, которые добавляют в очередь, будут получать ошибки. А хотелось бы, что они они добавляли в очередь, как обычно, но прекратился именно разбор.
авторЯ бы сделал перед остановкой очереди сначала unregister:

Попробовал так сделать. Но проблема та же - потом, когда делаю start_queue и register, уже существующие в очереди сообщения не разбираются, только новые, которые появляются в очереди после register.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39230916
landy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИМХО, callback возникает при попадании сообщения в очередь.
При остановке коллбэки не генерируются(или игнорируются процедурой обработки)
При старте - генерируются коллбэки при помещении в очередь, но те сообщения что в очереди уже вчера сгенерировали коллбэки
Т е нужно это сообщения выбрать и опять поместить в очередь(сгенерируется коллбэк)
Либо выбрать и обработать
...
Рейтинг: 0 / 0
AQ и подписчики
    #39231022
HX
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня Ваш тесткейз не получился, возможно из-за порядка вызовов, возможно из-за того что пришлось править процедуру callback (у меня нет таких пакетов).

Проверьте есть ли сообщения тут SYS.AQ_SRVNTFN_TABLE_<N> ?
Сюда попадают сообщения сразу после enqueue в Вашу очередь, при наличии зарегистрированного callback. Если подписчик не зарегистрирован, то сообщения сюда не кладутся при enqueue и никакого оповещения по таким messages в Вашей очереди не будет.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39231039
rybingleb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
landyИМХО, callback возникает при попадании сообщения в очередь.
При остановке коллбэки не генерируются(или игнорируются процедурой обработки)
При старте - генерируются коллбэки при помещении в очередь, но те сообщения что в очереди уже вчера сгенерировали коллбэки
Т е нужно это сообщения выбрать и опять поместить в очередь(сгенерируется коллбэк)
Либо выбрать и обработать

Скорее всего. Жаль, то есть получается, что в дополнение к процедуре callback, надо будет писать что-то, что будет разбирать сообщения в случае остановки очереди.

авторПроверьте есть ли сообщения тут SYS.AQ_SRVNTFN_TABLE_<N> ?
Сюда попадают сообщения сразу после enqueue в Вашу очередь, при наличии зарегистрированного callback. Если подписчик не зарегистрирован, то сообщения сюда не кладутся при enqueue и никакого оповещения по таким messages в Вашей очереди не будет.

Есть строки в SYS.AQ_SRVNTFN_TABLE. При enqueue как раз все срабатывает как надо. Вопрос был про обработку сообщения из очереди, после остановки dequeue.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39231099
kva6513
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rybinglebесть джоб, который постоянно запускает процедуру, которая делает dequeue. Мне это казалось немного костыльным.
Если вам кажется костыльным периодический поллинг очереди... Можно воспользоваться DBMS_ALERT, например, что-бы работать по событиям. В процедуру enqueue_msg добавляете отправку ALERT-а (DBMS_ALERT.SIGNAL). Джоб, занимающийся разборкой очереди делаете постоянно выполняющимся. Если делать совсем красиво, то примерно так:
При старте джоба разбирается все, что есть в очереди, после чего вход в цикл и "засыпание" на ожидании ALERT-а (DBMS_ALERT.WAITONE);

С ALERT-ом передавать параметр-команду - сигнализирующую о назначении ALERT-а, команд будет четыре:

Проверить очередь на наличие сообщений - проверка выполняется во вложенном цикле из которого выходим по событию отсутствия сообщений в очереди;

Перейти в состояние "MAINTENANCE" - обрабатываются только команды завершения работы и возврата в нормальный режим обработки, разбор очереди не выполняется;

Перейти в состояние нормальной обработки;

Завершить работу джоба;

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

PS: Вместо передачи параметра с ALERT-ом можно объявить необходимое их количество, но на мое сугубое HO - использование DBMS_ALERT.WAITONE предпочтительнее DBMS_ALERT.WAITANY.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39232063
Еще одно предложение: сделать две очереди. В одну помещать сообщения, а из другой вычитывать агентом. Между ними, настроить propagation, и "разруливать" на этом уровне.
...
Рейтинг: 0 / 0
AQ и подписчики
    #39259334
Egoza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rybingleb,

К какому решение в итоге пришли? У меня сейчас аналогичная дилемма с dequeue
...
Рейтинг: 0 / 0
AQ и подписчики
    #39261096
brzl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В подписчик добавить цикл
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
  begin
      loop
        dbms_aq.dequeue(queue_name => 'Q_NAME', dequeue_options => l_dequeue_options,
                        message_properties => l_deq_msg_properties, payload => l_payload,
                        msgid => l_deq_msgid);
      --do stmg
        commit;
      end loop;                 
  exception
    when others then
      if sqlcode = -25228 then --queue_empty
         commit;
      else raise;
      end if;
  end;
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / AQ и подписчики
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]