Форум OlegON > Компьютеры и Программное обеспечение > Операционные системы и программное обеспечение > Oracle

Как пресечь лавинообразный рост одинаковых запросов

19.06.2021 12:27


20.04.2021 14:57
OlegON
 
Достаточно часто бывает в базе, что ее начинают DoSить однотипными запросами. Кривой долгий запрос просочится от разработчиков, какие-то блокировки или еще что-то, но ситуация лавинообразная, однотипных запросов становится все больше, больше, сотни, тысячи, пока не закончатся процессы или сам сервер не погрузится в своп. Я поковырялся среди штатных средств ресурсменеджера, в том числе новомодные карантины от 19с, ничего подходящего не нашел. Решил сделать джоб, ежеминутно оценивающий ситуацию и, если 10 одинаковых запросов работают уже больше 10 секунд, то все такие запросы убивать. Надо понимать, что если забьется очередь джобов, то будет "ой", но джобу повысим приоритет до максимального 1 против 3 по умолчанию, так что если джобы вообще не сдохнут (у меня это одновременно с лавиной и не бывает), то все будет под контролем.

SQL код:
create or replace procedure disconnect_mass_sql is
begin
for c in (select sid,serial# from v$session where sql_id in (select sql_id from v$session where sql_id is not null and status='ACTIVE' and last_call_et>10 group by sql_id having count(sql_id)>10))
loop
begin
execute immediate
'alter system disconnect session ''' || c.sid || ',' || c.serial# || ''' immediate';
exception when others then null;
end;
end loop;
end;

SQL код:
BEGIN
DBMS_SCHEDULER
.CREATE_JOB (
job_name => 'kill_mass_sql',
job_type => 'PLSQL_BLOCK',
job_action => '
begin 
disconnect_mass_sql;
disconnect_mass_sql;
disconnect_mass_sql;
exception when others then null; 
end;
'
,
repeat_interval => 'FREQ=MINUTELY; INTERVAL=1;',
enabled => TRUE
);
END;

SQL код:
begin DBMS_SCHEDULER.set_attribute (name=> 'kill_mass_sql',attribute => 'job_priority',value => 1); end;

06.06.2021 19:23
OlegON
 
По результатам обкатки могу сказать следующее, раз в минуту запускать безнадежно, валится за несколько секунд при хорошей атаке.
Для Супермага и отчетов по количеству лучше брать 10, для некоторых других баз - 5. Соответственно, подправленный вариант ниже (добавил выкидывание неактивных блокирующих)
SQL код:
BEGIN
DBMS_SCHEDULER
.CREATE_JOB (
job_name => 'kill_mass_sql',
job_type => 'PLSQL_BLOCK',
job_action => '
begin 
disconnect_mass_sql;
exception when others then null; 
end;
'
,
repeat_interval => 'FREQ=SECONDLY; INTERVAL=5;',
enabled => TRUE
);
END;
/  

begin DBMS_SCHEDULER.set_attribute (name=> 'kill_mass_sql',attribute => 'job_priority',value => 1); end;
/  

create or replace procedure disconnect_mass_sql is
begin
for c in (select sid,serial# from v$session where sql_id in (select sql_id from v$session where sql_id is not null and status='ACTIVE' and last_call_et>5 group by sql_id having count(sql_id)>10))
loop
begin
execute immediate
'alter system disconnect session ''' || c.sid || ',' || c.serial# || ''' immediate';
exception when others then null;
end;
end loop;
begin for c in (select sid,serial# from v$session where status='INACTIVE' and sid in (select final_blocking_session from v$session)) loop begin execute immediate 'alter system disconnect session ''' || c.sid || ',' || c.serial# || ''' immediate'; exception when others then null; end; end loop; end;
end;


Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.