查看和终止 Oracle 连接会话以及正在执行的 SQL 语句
作者: 不剪发的Tony老师
毕业于北京航空航天大学,十多年数据库管理与开发经验,目前在一家全球性的金融公司从事数据库架构设计。CSDN学院签约讲师以及GitChat专栏作者。csdn上的博客收藏于以下地址:https://tonydong.blog.csdn.net
文章目录
查看当前连接的会话
终止正在执行的 SQL 语句
终止指定的连接会话
通过 SQL 命令终止连接会话
通过操作系统命令终止连接会话
总结
大家好,我是只谈技术不剪发的 Tony 老师。作为 DBA,有时候为了执行管理操作需要终止当前的用户会话;当某个 SQL
语句长时间运行并占用大量系统资源时,我们也可能需要手动终止正在执行的语句。因此,今天我们来讨论一下如何查看和终止 Oracle
的连接会话,以及正在执行的 SQL 语句。
查看当前连接的会话
Oracle 系统视图 V$SESSION 和对应的 GV$SESSION(全局视图主要用于 RAC 环境)提供了当前所有会话的相关信息。例如:
select inst_id, sid, serial#, username,
status, server, program, sql_id
from gv$session
where type != 'BACKGROUND'
and username is not null
and nvl(osuser,'x') <> 'SYSTEM';
INST_ID|SID|SERIAL#|USERNAME|STATUS |SERVER |PROGRAM |SQL_ID |
-------|---|-------|--------|--------|---------|----------------------------------------|-------------|
1|143| 9323|TONY |ACTIVE |DEDICATED|DBeaver 7.1.3 - SQLEditor <Script-2.sql>|9b1bawv3upw70|
1|265| 24368|TONY |INACTIVE|DEDICATED|DBeaver 7.1.3 - Main |3fnstj6ydy4xk|
1|399| 16226|TONY |INACTIVE|DEDICATED|sqlplus@sqlhost (TNS V1-V3) | |
以上查询只返回了用户的连接会话,不包括后台进程的连接会话。其中,
inst_id 是会话所在的实例 id;
sid 是会话标识符,serial# 是会话序列号,两者唯一确定实例中的会话;
username 是连接数据库的用户;
status 是会话的状态,例如 ACTIVE、INACTIVE、KILLED 等;
server 是服务器的类型,例如 DEDICATED、SHARED 等;
program 是会话客户端的应用程序名;
sql_id 是正在执行的 SQL 语句 id。
📝关于 V$SESSION 视图的更多字段可以参考官方文档。
终止正在执行的 SQL 语句
从 Oracle 18c 开始增加了ALTER SYSTEM CANCEL SQL命令,可以用于终止指定会话中正在执行的 SQL 语句,但不会终止连接会话。该语句的语法如下:
ALTER SYSTEM CANCEL SQL 'sid, serial# [, @inst_id][, sql_id]';
其中,
sid 是会话标识符;
serial# 是会话序列号;
inst_id 是实例 id,如果省略表示当前实例;
sql_id 是 SQL 标识符,如果省略表示终止该会话中正在运行的语句。
以上输入信息都可以通过查询上文中的 V$SESSION 或者 GV$SESSION 视图获得。使用该语句可以终止高负载的 SQL 语句;如果终止的是 DML 语句,该语句将会被回滚。
我们首先在一个会话(sid = 399、serial# = 16226)中执行以下语句:
SQL> EXEC DBMS_LOCK.sleep(300);
该会话将会睡眠 300 秒,然后在另一个会话中终止该语句(可以再次查询 GV$SESSION 视图获得相关信息):
-- 另一个会话
ALTER SYSTEM CANCEL SQL '399, 16226';
此时,上面的第一个会话返回以下错误:
SQL> EXEC DBMS_LOCK.sleep(300);
BEGIN DBMS_LOCK.sleep(300); END;
*
ERROR at line 1:
ORA-01013: user requested cancel of current operation
ORA-06512: at "SYS.DBMS_LOCK", line 205
ORA-06512: at line 1
📝如果想要查看会话中正在执行的 SQL 语句内容,可以通过 sql_id 字段关联查询系统视图 V$SQL 或者 GV$SQL。
终止指定的连接会话
通过 SQL 命令终止连接会话
⚠️如果终止了错误的会话,可能会造成严重的影响,因此在确定要终止的会话时要格外小心。如果终止了后台进程对应的会话,将会导致实例崩溃。
当会话终止被时,该会话的所有活动事务都会被回滚,并且该会话持有的资源(例如锁和内存)将立即释放。终止用户会话的基于命令如下:
ALTER SYSTEM KILL SESSION 'sid, serial# [, @inst_id]';
其中,
sid 是会话标识符;
serial# 是会话序列号;
inst_id 是实例 id,如果省略表示当前实例。
以上输入信息都可以通过查询上文中的 V$SESSION 或者 GV$SESSION 视图获得。
我们使用以下语句终止指定会话(sid = 399、serial# = 16226):
alter system kill session '399, 16226';
此时再次查询 gv$session 可以看到该会话的状态为 KILLED:
select inst_id, sid, serial#, username,
status, server, program, sql_id
from gv$session s
where type != 'BACKGROUND'
and username is not null
and nvl(osuser,'x') <> 'SYSTEM';
INST_ID|SID|SERIAL#|USERNAME|STATUS |SERVER |PROGRAM |SQL_ID |
-------|---|-------|--------|--------|---------|----------------------------------------|-------------|
1|143| 9323|TONY |ACTIVE |DEDICATED|DBeaver 7.1.3 - SQLEditor <Script-2.sql>|b3upx6u952qfb|
1|265| 24368|TONY |INACTIVE|DEDICATED|DBeaver 7.1.3 - Main |3fnstj6ydy4xk|
1|399| 16226|TONY |KILLED |DEDICATED|sqlplus@sqlhost (TNS V1-V3) | |
如果我们在被终止的会话中执行操作,将会返回以下错误:
SQL> select 1 from dual;
select 1 from dual
*
ERROR at line 1:
ORA-00028: your session has been killed
SQL> select 1 from dual;
select 1 from dual
*
ERROR at line 1:
ORA-01012: not logged on
Process ID: 27994
Session ID: 399 Serial number: 16226
ALTER SYSTEM KILL SESSION 语句实际上并不会立即终止会话,它只是请求会话自己终止。在某些情况下,例如等待远程数据库的响应或者事务的回滚时,会话不会立即终止,而是等待当前操作完成。此时会话的状态为 KILLED,表示“标记为终止”。
ALTER SYSTEM KILL SESSION 命令支持使用 IMMEDIATE 选项:
ALTER SYSTEM KILL SESSION 'sid, serial# [, @inst_id]' IMMEDIATE;
IMMEDIATE 选项不会改变该命令执行的操作,但是会立即返回,而不会等待会话被终止。
除了以上命令之外,ALTER SYSTEM DISCONNECT SESSION 语句也可以用于终止会话:
DISCONNECT SESSION 'sid, serial#' POST_TRANSACTION;
DISCONNECT SESSION 'sid, serial#' IMMEDIATE;
该命令与 ALTER SYSTEM KILL SESSION 语句不同之处在于它会终止专用服务器进程(或者共享服务器进程中的虚拟链路,相当于通过操作系命令终止服务器进程。其中 POST_TRANSACTION 选项表示等待正在执行中的事务结束后终止连接,IMMEDIATE 选项表示立即断开连接并且回滚事务。
对于上面终止会话的示例(如果没有执行的话),也可以使用以下语句实现相同的目的:
alter system disconnect session '399, 16226' post_transaction;
这种方式可以避免通过操作系统命令终止会话,减少了错误操作的风险。
通过操作系统命令终止连接会话
如果想要通过操作系统命令终止会话,首先需要找出会话对应的操作系统进程 id,可以通过 V$PROCESS 或者 GV$PROCESS 进行查看:
select s.inst_id,
s.sid,
s.serial#,
s.sql_id,
p.spid,
s.username,
s.status,
s.server,
s.program
from gv$session s
join gv$process p on p.addr = s.paddr and p.inst_id = s.inst_id
where s.type != 'BACKGROUND'
and s.username is not null
and nvl(s.osuser,'x') <> 'SYSTEM';
INST_ID|SID|SERIAL#|SQL_ID |SPID |USERNAME|STATUS |SERVER |PROGRAM |
-------|---|-------|-------------|-----|--------|--------|---------|----------------------------------------|
1|399| 22691| |12195|TONY |INACTIVE|DEDICATED|sqlplus@sqlhost (TNS V1-V3) |
1|265| 24368|3fnstj6ydy4xk|9152 |TONY |INACTIVE|DEDICATED|DBeaver 7.1.3 - Main |
1|143| 9323|7yyukqn3pkt89|9193 |TONY |ACTIVE |DEDICATED|DBeaver 7.1.3 - SQLEditor <Script-2.sql>|
其中,spid 就是会话对应的操作系统进程 id。
有了进程 id ,就可以通过操作系统命令终止相应的进程。对于 Unix/Linux 操作系统,可以使用 kill 命令终止进程:
kill spid
kill -9 spid
其中,-9 表示强制终止。在终止进程之前也可以使用 ps 命令进行二次确认:
ps -ef | grep ora
我们使用以下命令终止会话(sid = 399、serial# = 22691)对应的操作系统进程(12195):
[root@sqlhost ~]# kill 12195
此时,如果在该会话中执行任何语句都会返回错误:
SQL> select 1 from dual;
select 1 from dual
*
ERROR at line 1:
ORA-03135: connection lost contact
Process ID: 12195
Session ID: 399 Serial number: 22691
⚠️Oracle 12c 开始支持 Unix/Linux 环境下的多线程模型;如果使用了这种模型,不要使用操作系统命令终止会话,否则会一次终止多个会话。
对于 Windows 操作系统,可以使用 orakill 命令行工具终止进程:
orakill sid spid
其中,sid 是会话标识符,spid 是会话对应的进程 id。
总结
Oracle 提供了几种终止连接会话/进程和运行中的 SQL 语句的方法。首先可以通过 GV$SESSION 和 GV$PROCESS 等视图查看会话和对应的系统进程信息,然后使用 ALTER SYSTEM KILL SESSION 或者 ALTER SYSTEM DISCONNECT SESSION 命令终止连接会话,或者利用操作系统命令(kill、orakill)终止相应的进程;另外,也可以使用 ALTER SYSTEM CANCEL SQL 命令终止正在运行的 SQL 语句。
如果觉得文章对你有用,欢迎关注❤️、评论📝、点赞👍!