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

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

文章目錄

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

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

Oracle 系統(tǒng)視圖 V$SESSION 和對應(yīng)的 GV$SESSION(全局視圖主要用于 RAC 環(huán)境)提供了當(dāng)前所有會話的相關(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)             |             |

 

以上查詢只返回了用戶的連接會話,不包括后臺進程的連接會話。其中,

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

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

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

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

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

 

其中,

    sid 是會話標識符;
    serial# 是會話序列號;
    inst_id 是實例 id,如果省略表示當(dāng)前實例;
    sql_id 是 SQL 標識符,如果省略表示終止該會話中正在運行的語句。

以上輸入信息都可以通過查詢上文中的 V$SESSION 或者 GV$SESSION 視圖獲得。使用該語句可以終止高負載的 SQL 語句;如果終止的是 DML 語句,該語句將會被回滾。

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

SQL> EXEC DBMS_LOCK.sleep(300);

 

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

-- 另一個會話
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

 

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

終止指定的連接會話
通過 SQL 命令終止連接會話

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

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

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

 

其中,

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

以上輸入信息都可以通過查詢上文中的 V$SESSION 或者 GV$SESSION 視圖獲得。

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

alter system kill session '399, 16226';

 

此時再次查詢 gv$session 可以看到該會話的狀態(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)             |             |

 

如果我們在被終止的會話中執(zhí)行操作,將會返回以下錯誤:

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

ALTER SYSTEM KILL SESSION 命令支持使用 IMMEDIATE 選項:

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

 

IMMEDIATE 選項不會改變該命令執(zhí)行的操作,但是會立即返回,而不會等待會話被終止。

除了以上命令之外,ALTER SYSTEM DISCONNECT SESSION 語句也可以用于終止會話:

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

 

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

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

alter system disconnect session '399, 16226' post_transaction;

 

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

如果想要通過操作系統(tǒng)命令終止會話,首先需要找出會話對應(yīng)的操作系統(tǒng)進程 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 就是會話對應(yīng)的操作系統(tǒng)進程 id。

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

kill spid
kill -9 spid

 

其中,-9 表示強制終止。在終止進程之前也可以使用 ps 命令進行二次確認:

ps -ef | grep ora

 

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

[root@sqlhost ~]# kill 12195

 

此時,如果在該會話中執(zhí)行任何語句都會返回錯誤:

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 環(huán)境下的多線程模型;如果使用了這種模型,不要使用操作系統(tǒng)命令終止會話,否則會一次終止多個會話。

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

orakill sid spid

 

其中,sid 是會話標識符,spid 是會話對應(yīng)的進程 id。
總結(jié)

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

如果覺得文章對你有用,歡迎關(guān)注??、評論??、點贊??!