Я хотел бы иметь возможность убить пользовательский запрос в Oracle 10.2.0.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
Я нашел уловку. Я понятия не имею, насколько это безопасно для игры, но это работает. Существует событие 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?
@ Бен, если хочешь - шесть с половиной дюжин на самом деле
В идеале приложение пользователя должно иметь возможность отмены запроса (через 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/
TOAD делает это, выполняя запрос во втором сеансе; если оператор отменяет запрос, TOAD завершает вторую сессию.