1.1、会话(Session)与连接(Connection)

在 Oracle 中,连接(Connection)是客户端与数据库之间的通信链路,会话(Session)是数据库为用户建立的状态上下文。一个连接可以对应多个会话(如连接池),一个会话也可以没有连接(如共享服务器模式)。

实例:连接与会话的概念区分

 S — Situation(场景):应用团队报告"数据库连接数满了",但 DBA 检查发现 PROCESSES 参数设置为 500,当前连接数只有 300。

 T — Task(任务):分析连接数与会话数的差异,找到真正的问题。

A — Action(行动):

        1、查看当前连接数和会话数:

        -- 连接数(操作系统层面)

        SELECT COUNT(*) FROM V$SESSION WHERE TYPE = 'USER';

        2、查看会话数(数据库层面):

        SELECT COUNT(*) FROM V$SESSION;  -- 返回 450(包含后台进程会话)

        3、查看各类型会话分布:

        SELECT TYPE, COUNT(*) FROM V$SESSION GROUP BY TYPE;

        -- USER: 300, BACKGROUND: 120, OTHER: 30

        4、查看 PROCESSES 参数:

        SHOW PARAMETER PROCESSES;  --500

        5、 分析:后台进程 + 用户会话 = 420,接近上限 500

        -- 解决方案:增加 PROCESSES 或优化连接池

R — Result(结果):问题是 PROCESSES 参数包含了所有进程(用户进程 + 后台进程 + 系统进程),不仅仅是用户连接。增加了 PROCESSES 到 800,并优化了应用连接池配置。

1.2、会话解控与管理

实例:定位并终止阻塞会话

S — Situation(场景):某关键业务表被锁,大量 INSERT 操作挂起,应用报 ORA-00054: resource busy and acquire with NOWAIT specified。

T — Task(任务):快速定位阻塞源并解除锁定。

A — Action(行动):

        1、查找阻塞会话:

        SELECT s.SID, s.SERIAL#, s.USERNAME, s.STATUS,s.MACHINE, s.PROGRAM, s.LOGON_TIME,l.TYPE, l.ID1, l.ID2  FROM V$SESSION s JOIN V$LOCK l ON s.SID = l.SID WHERE l.BLOCK > 0;

        2、查找被阻塞的会话

        SELECT s.SID, s.USERNAME, s.STATUS, s.SQL_ID FROM V$SESSION s WHERE s.BLOCKING_SESSION IS NOT NULL;

        3、查看阻塞会话正在执行的 SQL:

         SELECT SQL_TEXT FROM V$SQL WHERE SQL_ID = (SELECT SQL_ID FROM V$SESSION WHERE SID = <blocking_sid>);

        4、 终止阻塞会话:

        ALTER SYSTEM KILL SESSION '<SID>,<SERIAL#>' IMMEDIATE;

        -- IMMEDIATE 立即终止,无需等待

        5、验证锁释放

        SELECT * FROM V$LOCK WHERE BLOCK > 0;  -- 无返回,阻塞已解除

R — Result(结果):在 30 秒内定位阻塞源并终止会话,业务恢复正常。后续建立了锁等待告警,超过 60 秒自动通知 DBA。

1.3、进程限制与 PROCESSES 参数

实例:ORA-00020 错误排查

S — Situation(场景):数据库突然拒绝新连接,报 ORA-00020: maximum number of processes exceeded。

T — Task(任务):紧急处理并根治进程耗尽问题。

A — Action(行动):

        1、紧急处理:使用 SYSDBA 连接(SYSDBA 连接不受 PROCESSES 限制):

        sqlplus / as sysdba

        2、查看当前进程数和限制:

        SELECT COUNT(*) FROM V$PROCESS;

        SHOW PARAMETER PROCESSES;

        3、找到占用大量连接的应用:

        SELECT MACHINE, PROGRAM, COUNT(*) AS CNT FROM V$SESSION GROUP BY MACHINE, PROGRAM ORDER BY CNT DESC;

        4、终止异常应用的空闲会话:

        SELECT 'ALTER SYSTEM KILL SESSION "' || SID || ',' || SERIAL# || '" IMMEDIATE;' FROM V$SESSION WHERE MACHINE LIKE '<异常主机>%' AND STATUS = 'INACTIVE' AND LAST_CALL_ET > 3600;

        5、长期解决方案:

         -- 增加 PROCESSES 参数

        ALTER SYSTEM SET PROCESSES = 1000 SCOPE=SPFILE;

        -- 优化应用连接池配置

        -- 设置 SQLNET.EXPIRE_TIME 检测死连接

        R — Result(结果):紧急恢复了数据库连接。长期通过增加 PROCESSES、优化连接池、配置死连接检测三管齐下,彻底解决了进程耗尽问题。

1.4、会话级参数调整

实例:会话集参数优化特定查询

S — Situation(场景):某报表查询使用了错误的执行计划(全表扫描),需要临时增大该会话的 SORT_AREA_SIZE 以加速排序,同时不影响其他会话。

T — Task(任务):在会话级别调整参数,优化特定查询。

 A — Action(行动):

        1、创建专用会话并调整参数:

         ALTER SESSION SET SORT_AREA_SIZE = 104857600;  -- 100MB

        ALTER SESSION SET HASH_AREA_SIZE = 104857600;   -- 100MB

        ALTER SESSION SET WORKAREA_SIZE_POLICY = MANUAL;

        2、执行优化后的查询:

        SELECT /*+ PARALLEL(4) */ department_id, SUM(salary)  FROM employees GROUP BY department_id ORDER BY 2 DESC;

        3、恢复默认参数:

        ALTER SESSION SET WORKAREA_SIZE_POLICY = AUTO;

        4、或者使用 SQL Profile 固定执行计划:

         -- 使用 SQL Tuning Advisor

 DECLARE
  l_task VARCHAR2(30);
BEGIN
  l_task := DBMS_SQLTUNE.CREATE_TUNING_TASK(sql_id => '<SQL_ID>');
  DBMS_SQLTUNE.EXECUTE_TUNING_TASK(l_task);
END;

R — Result(结果):会话级参数调整使排序操作在内存中完成,查询时间从 120 秒降至 8 秒。SQL Profile 固定了最优执行计划,后续无需手动调整。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐