Как я могу убить все сеансы, соединяющиеся с моей базой данных оракула?
Мне нужно быстро (и принудительно) прекратить все внешние сеансы, соединяющиеся с моей базой данных Oracle, без присмотра администратора.
Я не хочу просто блокировать базу данных и позволить пользователям корректно завершать работу.
Как бы я это написал?
10 ответов
Этот ответ находится под сильным влиянием разговора здесь: http://www.tek-tips.com/viewthread.cfm?qid=1395151&page=3
ALTER SYSTEM ENABLE RESTRICTED SESSION;
begin
for x in (
select Sid, Serial#, machine, program
from v$session
where
machine <> 'MyDatabaseServerName'
) loop
execute immediate 'Alter System Kill Session '''|| x.Sid
|| ',' || x.Serial# || ''' IMMEDIATE';
end loop;
end;
Я пропускаю сеансы уничтожения, происходящие на сервере базы данных, чтобы избежать уничтожения соединений Oracle с самим собой.
Перед убийством сессий, если возможно
ALTER SYSTEM ENABLE RESTRICTED SESSION;
чтобы остановить новые сеансы от подключения.
Некоторое время я использовал что-то подобное, чтобы убить мои сеансы на общем сервере. Первая строка 'where' может быть удалена, чтобы убить все сеансы не 'sys':
BEGIN
FOR c IN (
SELECT s.sid, s.serial#
FROM v$session s
WHERE (s.Osuser = 'MyUser' or s.MACHINE = 'MyNtDomain\MyMachineName')
AND s.USERNAME <> 'SYS'
AND s.STATUS <> 'KILLED'
)
LOOP
EXECUTE IMMEDIATE 'alter system kill session ''' || c.sid || ',' || c.serial# || '''';
END LOOP;
END;
Если вы хотите запретить новым пользователям подключаться, но позволить текущим сеансам продолжаться до тех пор, пока они не станут неактивными, вы можете перевести базу данных в режим QUIESCE:
ALTER SYSTEM QUIESCE RESTRICTED;
Из Руководства администратора базы данных Oracle:
Не-DBA активные сеансы будут продолжаться, пока они не станут неактивными. Активный сеанс - это сеанс, который в данный момент находится внутри транзакции, запроса, выборки или оператора PL/SQL; или сеанс, который в настоящее время содержит какие-либо общие ресурсы (например, ставит в очередь). Неактивные сеансы не могут становиться активными... Как только все сеансы не DBA становятся неактивными, инструкция ALTER SYSTEM QUIESCE RESTRICTED завершается, и база данных находится в состоянии покоя
Дополнительная информация
Важные изменения в Oracle 11g для изменения сеанса уничтожения сеанса
Автор Oracle Младен Гогала отмечает, что теперь для завершения сеанса при использовании столбца inst_id требуется знак @:
alter system kill session '130,620,@1';
Я нашел следующий фрагмент кода полезным. Взято из: http://jeromeblog-jerome.blogspot.com/2007/10/how-to-unlock-record-on-oracle.html
select
owner||'.'||object_name obj ,
oracle_username||' ('||s.status||')' oruser ,
os_user_name osuser ,
machine computer ,
l.process unix ,
s.sid||','||s.serial# ss ,
r.name rs ,
to_char(s.logon_time,'yyyy/mm/dd hh24:mi:ss') time
from v$locked_object l ,
dba_objects o ,
v$session s ,
v$transaction t ,
v$rollname r
where l.object_id = o.object_id
and s.sid=l.session_id
and s.taddr=t.addr
and t.xidusn=r.usn
order by osuser, ss, obj
;
Затем побежал:
Alter System Kill Session '<value from ss above>'
;
Чтобы убить отдельные сессии.
Чтобы ответить на заданный вопрос, вот наиболее точный SQL для выполнения задачи, вы можете объединить его с циклом PL/SQL для фактического выполнения операторов kill:
select ses.USERNAME,
substr(MACHINE,1,10) as MACHINE,
substr(module,1,25) as module,
status,
'alter system kill session '''||SID||','||ses.SERIAL#||''';' as kill
from v$session ses LEFT OUTER JOIN v$process p ON (ses.paddr=p.addr)
where schemaname <> 'SYS'
and not exists
(select 1
from DBA_ROLE_PRIVS
where GRANTED_ROLE='DBA'
and schemaname=grantee)
and machine!='yourlocalhostname'
order by LAST_CALL_ET desc;
Попробуйте вызвать на вход
Если вы попытаетесь отключить пользователей, вы не должны позволять им подключаться.
Есть и пример такого триггера.
CREATE OR REPLACE TRIGGER rds_logon_trigger
AFTER LOGON ON DATABASE
BEGIN
IF SYS_CONTEXT('USERENV','IP_ADDRESS') not in ('192.168.2.121','192.168.2.123','192.168.2.233') THEN
RAISE_APPLICATION_ERROR(-20003,'You are not allowed to connect to the database');
END IF;
IF (to_number(to_char(sysdate,'HH24'))< 6) and (to_number(to_char(sysdate,'HH24')) >18) THEN
RAISE_APPLICATION_ERROR(-20005,'Logon only allowed during business hours');
END IF;
END;
Если Oracle работает в Unix /Linux, тогда мы можем выполнить grep для всех клиентских подключений и убить его
grep весь процесс клиента oracle:
ps -ef | grep LOCAL = NO | grep -v grep | awk '{print $ 2}' | туалет
Убить весь процесс клиента oracle:
убить -9 ps -ef | grep LOCAL=NO | grep -v grep | awk '{print $2}'