Можно ли убить один запрос в оракуле, не прерывая сеанс?

Я хотел бы иметь возможность убить пользовательский запрос в Oracle 10.2.0.4, не уничтожая весь их сеанс. Это позволит завершить запрос, но не вывести пользователя из сеанса, чтобы он мог продолжить выполнение других запросов. Это вообще возможно? Или тупой молоток, убивающий сеанс, - единственный способ остановить выполнение запроса?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
15
0
22 676
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете посмотреть ограничения ресурсов:

«Если пользователь превышает предел ресурса на уровне вызова, Oracle останавливает обработку оператора, откатывает его и возвращает ошибку. Однако все предыдущие операторы текущей транзакции остаются нетронутыми, а сеанс пользователя остается подключенным. "

Это предполагает, что причиной отмены SQL является ограничение ресурсов, а не обновление неправильного набора строк (например). Я подозреваю, что вы не сможете повлиять на выполняющийся в данный момент SQL, добавив лимит ресурсов.

http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/security.htm#i13767
http://download.oracle.com/docs/cd/B19306_01/server.102/b14231/dbrm.htm#i1010776

Я подозреваю, что это возможно, поскольку вы можете сделать это в TOAD. Во время выполнения запроса появляется диалоговое окно «Отмена», которое можно нажать, чтобы остановить запрос.

Как это реализовано, не знаю, но мне тоже было бы интересно узнать.

Если вы используете java, есть метод java.sql.Statement cancel (), который должен это делать. См. Здесь некоторые примечания и ограничения ...

http://download.oracle.com/docs/cd/B14117_01/java.101/b10979/tips.htm#BACDAICJ

TOAD делает это, выполняя запрос во втором сеансе; если оператор отменяет запрос, TOAD завершает вторую сессию.

Jeffrey Kemp 19.04.2011 05:47
Ответ принят как подходящий

Я нашел уловку. Я понятия не имею, насколько это безопасно для игры, но это работает. Существует событие Oracle 10237, которое описывается как «simulate ^ C (для тестирования)».

У вас должны быть SID и SERIAL # сеанса, который вы хотите прервать.

Вызовите SYS.DBMS_SYSTEM.SET_EV (Сид, серийный номер, 10237, 1, ''), чтобы активировать событие в целевом сеансе. Любой выполняющийся в данный момент оператор должен быть прерван (получение «ORA-01013: пользователь запросил отмену текущей операции»). Пока событие установлено, любые дальнейшие операторы, которые сеанс пытается выполнить, немедленно завершаются с той же ошибкой.

Чтобы деактивировать событие, сделайте тот же вызов с четвертым параметром, установленным на «0». После этого сеанс снова сможет выполнять операторы.

Обратите внимание, что целевой сеанс должен определить, что событие установлено, что может занять время или может никогда не произойти, в зависимости от того, что он делает. Таким образом, вы не можете просто быстро включить и выключить событие. Вам нужно будет включить его, убедиться, что рассматриваемый оператор остановился, а затем выключить его.

Вот пример кода. Это предназначено для запуска как анонимного блока в SQLPlus с соответствующими переменными подстановки "sid" и "serial". Вы можете превратить его в хранимую процедуру с этими параметрами в качестве параметров.

DECLARE
  l_status  v$session.status%TYPE;
BEGIN

  dbms_system.set_ev( &sid, &serial, 10237, 1, '');

  LOOP
    SELECT status INTO l_status FROM v$session
      WHERE sid = &sid and serial# = &serial;
    EXIT WHEN l_status='INACTIVE';
  END LOOP;

  dbms_system.set_ev( &sid, &serial, 10237, 0, '');
END;

Хороший. Возможно, более надежное условие выхода из этого цикла - например, если статус сеанса становится «УБИТ» или «ЗАПРЕЩЕНО», а также, возможно, автоматический тайм-аут.

Jeffrey Kemp 05.06.2009 07:11

Разве вы не вышли бы, если статус не АКТИВЕН, вместо @Jeffrey?

Ben 11.07.2014 00:16

@ Бен, если хочешь - шесть с половиной дюжин на самом деле

Jeffrey Kemp 11.07.2014 02:38

В идеале приложение пользователя должно иметь возможность отмены запроса (через OCICancel или эквивалент).

В противном случае лучше всего было бы использовать диспетчер ресурсов (если в Oracle EE), вы можете использовать DBMS_RESOURCE_MANAGER.SWITCH_CONSUMER_GROUP_FOR_SESS, чтобы установить целевой сеанс для группы потребителей CANCEL_SQL.

Еще один способ отмены запроса других сеансов, который не работает с клиентскими сеансами sqlplus Windows, - это отправить срочный сигнал процессу Oracle с помощью kill -URG (это взлом, не для повседневного использования)

Я уже писал о том, почему это работает:

http://blog.tanelpoder.com/2010/02/17/how-to-cancel-a-query-running-in-another-session/

Другие вопросы по теме