查看和終止 Oracle 連接會(huì)話(huà)以及正在執(zhí)行的 SQL 語(yǔ)句

作者: 不剪發(fā)的Tony老師
畢業(yè)于北京航空航天大學(xué),十多年數(shù)據(jù)庫(kù)管理與開(kāi)發(fā)經(jīng)驗(yàn),目前在一家全球性的金融公司從事數(shù)據(jù)庫(kù)架構(gòu)設(shè)計(jì)。CSDN學(xué)院簽約講師以及GitChat專(zhuān)欄作者。csdn上的博客收藏于以下地址:https://tonydong.blog.csdn.net

文章目錄

        查看當(dāng)前連接的會(huì)話(huà)
        終止正在執(zhí)行的 SQL 語(yǔ)句
        終止指定的連接會(huì)話(huà)
            通過(guò) SQL 命令終止連接會(huì)話(huà)
            通過(guò)操作系統(tǒng)命令終止連接會(huì)話(huà)
        總結(jié)

大家好,我是只談技術(shù)不剪發(fā)的 Tony 老師。作為 DBA,有時(shí)候?yàn)榱藞?zhí)行管理操作需要終止當(dāng)前的用戶(hù)會(huì)話(huà);當(dāng)某個(gè) SQL 語(yǔ)句長(zhǎng)時(shí)間運(yùn)行并占用大量系統(tǒng)資源時(shí),我們也可能需要手動(dòng)終止正在執(zhí)行的語(yǔ)句。因此,今天我們來(lái)討論一下如何查看和終止 Oracle 的連接會(huì)話(huà),以及正在執(zhí)行的 SQL 語(yǔ)句。
查看當(dāng)前連接的會(huì)話(huà)

Oracle 系統(tǒng)視圖 V$SESSION 和對(duì)應(yīng)的 GV$SESSION(全局視圖主要用于 RAC 環(huán)境)提供了當(dāng)前所有會(huì)話(huà)的相關(guān)信息。例如:

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)             |             |

 

以上查詢(xún)只返回了用戶(hù)的連接會(huì)話(huà),不包括后臺(tái)進(jìn)程的連接會(huì)話(huà)。其中,

    inst_id 是會(huì)話(huà)所在的實(shí)例 id;
    sid 是會(huì)話(huà)標(biāo)識(shí)符,serial# 是會(huì)話(huà)序列號(hào),兩者唯一確定實(shí)例中的會(huì)話(huà);
    username 是連接數(shù)據(jù)庫(kù)的用戶(hù);
    status 是會(huì)話(huà)的狀態(tài),例如 ACTIVE、INACTIVE、KILLED 等;
    server 是服務(wù)器的類(lèi)型,例如 DEDICATED、SHARED 等;
    program 是會(huì)話(huà)客戶(hù)端的應(yīng)用程序名;
    sql_id 是正在執(zhí)行的 SQL 語(yǔ)句 id。

    ??關(guān)于 V$SESSION 視圖的更多字段可以參考官方文檔。

終止正在執(zhí)行的 SQL 語(yǔ)句

從 Oracle 18c 開(kāi)始增加了ALTER SYSTEM CANCEL SQL命令,可以用于終止指定會(huì)話(huà)中正在執(zhí)行的 SQL 語(yǔ)句,但不會(huì)終止連接會(huì)話(huà)。該語(yǔ)句的語(yǔ)法如下:

ALTER SYSTEM CANCEL SQL 'sid, serial# [, @inst_id][, sql_id]';

 

其中,

    sid 是會(huì)話(huà)標(biāo)識(shí)符;
    serial# 是會(huì)話(huà)序列號(hào);
    inst_id 是實(shí)例 id,如果省略表示當(dāng)前實(shí)例;
    sql_id 是 SQL 標(biāo)識(shí)符,如果省略表示終止該會(huì)話(huà)中正在運(yùn)行的語(yǔ)句。

以上輸入信息都可以通過(guò)查詢(xún)上文中的 V$SESSION 或者 GV$SESSION 視圖獲得。使用該語(yǔ)句可以終止高負(fù)載的 SQL 語(yǔ)句;如果終止的是 DML 語(yǔ)句,該語(yǔ)句將會(huì)被回滾。

我們首先在一個(gè)會(huì)話(huà)(sid = 399、serial# = 16226)中執(zhí)行以下語(yǔ)句:

SQL> EXEC DBMS_LOCK.sleep(300);

 

該會(huì)話(huà)將會(huì)睡眠 300 秒,然后在另一個(gè)會(huì)話(huà)中終止該語(yǔ)句(可以再次查詢(xún) GV$SESSION 視圖獲得相關(guān)信息):

-- 另一個(gè)會(huì)話(huà)
ALTER SYSTEM CANCEL SQL '399, 16226';

 

此時(shí),上面的第一個(gè)會(huì)話(huà)返回以下錯(cuò)誤:

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

 

    ??如果想要查看會(huì)話(huà)中正在執(zhí)行的 SQL 語(yǔ)句內(nèi)容,可以通過(guò) sql_id 字段關(guān)聯(lián)查詢(xún)系統(tǒng)視圖 V$SQL 或者 GV$SQL。

終止指定的連接會(huì)話(huà)
通過(guò) SQL 命令終止連接會(huì)話(huà)

    ??如果終止了錯(cuò)誤的會(huì)話(huà),可能會(huì)造成嚴(yán)重的影響,因此在確定要終止的會(huì)話(huà)時(shí)要格外小心。如果終止了后臺(tái)進(jìn)程對(duì)應(yīng)的會(huì)話(huà),將會(huì)導(dǎo)致實(shí)例崩潰。

當(dāng)會(huì)話(huà)終止被時(shí),該會(huì)話(huà)的所有活動(dòng)事務(wù)都會(huì)被回滾,并且該會(huì)話(huà)持有的資源(例如鎖和內(nèi)存)將立即釋放。終止用戶(hù)會(huì)話(huà)的基于命令如下:

ALTER SYSTEM KILL SESSION 'sid, serial# [, @inst_id]';

 

其中,

    sid 是會(huì)話(huà)標(biāo)識(shí)符;
    serial# 是會(huì)話(huà)序列號(hào);
    inst_id 是實(shí)例 id,如果省略表示當(dāng)前實(shí)例。

以上輸入信息都可以通過(guò)查詢(xún)上文中的 V$SESSION 或者 GV$SESSION 視圖獲得。

我們使用以下語(yǔ)句終止指定會(huì)話(huà)(sid = 399、serial# = 16226):

alter system kill session '399, 16226';

 

此時(shí)再次查詢(xún) gv$session 可以看到該會(huì)話(huà)的狀態(tài)為 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)             |             |

 

如果我們?cè)诒唤K止的會(huì)話(huà)中執(zhí)行操作,將會(huì)返回以下錯(cuò)誤:

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 語(yǔ)句實(shí)際上并不會(huì)立即終止會(huì)話(huà),它只是請(qǐng)求會(huì)話(huà)自己終止。在某些情況下,例如等待遠(yuǎn)程數(shù)據(jù)庫(kù)的響應(yīng)或者事務(wù)的回滾時(shí),會(huì)話(huà)不會(huì)立即終止,而是等待當(dāng)前操作完成。此時(shí)會(huì)話(huà)的狀態(tài)為 KILLED,表示“標(biāo)記為終止”。

ALTER SYSTEM KILL SESSION 命令支持使用 IMMEDIATE 選項(xiàng):

ALTER SYSTEM KILL SESSION 'sid, serial# [, @inst_id]' IMMEDIATE;

 

IMMEDIATE 選項(xiàng)不會(huì)改變?cè)撁顖?zhí)行的操作,但是會(huì)立即返回,而不會(huì)等待會(huì)話(huà)被終止。

除了以上命令之外,ALTER SYSTEM DISCONNECT SESSION 語(yǔ)句也可以用于終止會(huì)話(huà):

DISCONNECT SESSION 'sid, serial#' POST_TRANSACTION;
DISCONNECT SESSION 'sid, serial#' IMMEDIATE;

 

該命令與 ALTER SYSTEM KILL SESSION 語(yǔ)句不同之處在于它會(huì)終止專(zhuān)用服務(wù)器進(jìn)程(或者共享服務(wù)器進(jìn)程中的虛擬鏈路,相當(dāng)于通過(guò)操作系命令終止服務(wù)器進(jìn)程。其中 POST_TRANSACTION 選項(xiàng)表示等待正在執(zhí)行中的事務(wù)結(jié)束后終止連接,IMMEDIATE 選項(xiàng)表示立即斷開(kāi)連接并且回滾事務(wù)。

對(duì)于上面終止會(huì)話(huà)的示例(如果沒(méi)有執(zhí)行的話(huà)),也可以使用以下語(yǔ)句實(shí)現(xiàn)相同的目的:

alter system disconnect session '399, 16226' post_transaction;

 

這種方式可以避免通過(guò)操作系統(tǒng)命令終止會(huì)話(huà),減少了錯(cuò)誤操作的風(fēng)險(xiǎn)。
通過(guò)操作系統(tǒng)命令終止連接會(huì)話(huà)

如果想要通過(guò)操作系統(tǒng)命令終止會(huì)話(huà),首先需要找出會(huì)話(huà)對(duì)應(yīng)的操作系統(tǒng)進(jìn)程 id,可以通過(guò) V$PROCESS 或者 GV$PROCESS 進(jìn)行查看:

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 就是會(huì)話(huà)對(duì)應(yīng)的操作系統(tǒng)進(jìn)程 id。

有了進(jìn)程 id ,就可以通過(guò)操作系統(tǒng)命令終止相應(yīng)的進(jìn)程。對(duì)于 Unix/Linux 操作系統(tǒng),可以使用 kill 命令終止進(jìn)程:

kill spid
kill -9 spid

 

其中,-9 表示強(qiáng)制終止。在終止進(jìn)程之前也可以使用 ps 命令進(jìn)行二次確認(rèn):

ps -ef | grep ora

 

我們使用以下命令終止會(huì)話(huà)(sid = 399、serial# = 22691)對(duì)應(yīng)的操作系統(tǒng)進(jìn)程(12195):

[root@sqlhost ~]# kill 12195

 

此時(shí),如果在該會(huì)話(huà)中執(zhí)行任何語(yǔ)句都會(huì)返回錯(cuò)誤:

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 開(kāi)始支持 Unix/Linux 環(huán)境下的多線(xiàn)程模型;如果使用了這種模型,不要使用操作系統(tǒng)命令終止會(huì)話(huà),否則會(huì)一次終止多個(gè)會(huì)話(huà)。

對(duì)于 Windows 操作系統(tǒng),可以使用 orakill 命令行工具終止進(jìn)程:

orakill sid spid

 

其中,sid 是會(huì)話(huà)標(biāo)識(shí)符,spid 是會(huì)話(huà)對(duì)應(yīng)的進(jìn)程 id。
總結(jié)

Oracle 提供了幾種終止連接會(huì)話(huà)/進(jìn)程和運(yùn)行中的 SQL 語(yǔ)句的方法。首先可以通過(guò) GV$SESSION 和 GV$PROCESS 等視圖查看會(huì)話(huà)和對(duì)應(yīng)的系統(tǒng)進(jìn)程信息,然后使用 ALTER SYSTEM KILL SESSION 或者 ALTER SYSTEM DISCONNECT SESSION 命令終止連接會(huì)話(huà),或者利用操作系統(tǒng)命令(kill、orakill)終止相應(yīng)的進(jìn)程;另外,也可以使用 ALTER SYSTEM CANCEL SQL 命令終止正在運(yùn)行的 SQL 語(yǔ)句。

如果覺(jué)得文章對(duì)你有用,歡迎關(guān)注??、評(píng)論??、點(diǎn)贊??!