oracle数据库卡顿排查

oracle数据库卡顿排查

最近工作中总是遇到现网操作卡顿的问题,利用deepseek查找一些测试思路。【侵删】

1、通过top命令查询数据库节点负载情况;

2、通过shell命令查询数据库连接数;

3、查询数据库有无死锁情况;

第一步

sql 复制代码
--查询oracle版本号和已安装组件,执行python连接时需要下载oracle client;
SELECT * FROM V$VERSION;
--查询指定表的所有列名,便于插入sql数据,下方python代码编写时需要;
SELECT LISTAGG(COLUMN_NAME, ', ') WITHIN GROUP (ORDER BY COLUMN_ID) AS column_list
FROM ALL_TAB_COLUMNS WHERE TABLE_NAME = 'ABC' ;
--数据库中所有表按逻辑读次数(访问频率)从高到低排序的统计结果,用于识别数据库中最频繁访问的热点表。也可用作性能分析,将这些表数据量增多,测试下功能交互是否卡顿。
SELECT owner, object_name, value AS logical_reads FROM v$segment_statistics WHERE statistic_name='logical reads' AND object_type='TABLE' ORDER BY value DESC ;

测试环境和现网的数据量不是一个等级,通过第三个sql查出来哪些表最频繁访问,然后先把这些表的数据构造到和现网数据量一个等级。构造方式是通过对当前表中所有数据进行翻倍。python代码如下:

python 复制代码
import cx_Oracle

DB_CONFIG = {
    'host': '192.168.xxx.xxx',
    'port': 1521,
    'user': 'abc',
    'password': 'password',
    'database': 'oracledb'
}

dsn = cx_Oracle.makedsn(DB_CONFIG['host'], DB_CONFIG['port'], service_name=DB_CONFIG['database'])
print(f"正在连接: {DB_CONFIG['user']}@{DB_CONFIG['host']}:{1521}/{'paidb'}")
print("-" * 50)
try:
    # 建立连接
    connection = cx_Oracle.connect(DB_CONFIG['user'], DB_CONFIG['password'], dsn)
    print("✅ 数据库连接成功!")

    # 创建游标
    cursor = connection.cursor()
    a=1
    # 这里的id加的数值要根据表的sequence决定,测试结束后记得删除构造的数据;
    for num in range(100000000000, 399000000001, 1000000000): # 这是插入300倍数据,总数301倍
        print(f"num={num}")
        # a+=1
        # print(a)
        sql_job = f'''INSERT INTO {Table1}
        SELECT ID + {num}, 字段1,字段2.. FROM {Table1} WHERE ID <= 25766729'''
        print(f'执行sql是{sql_job}')
        cursor.execute(sql_job)
        rows_inserted = cursor.rowcount
        connection.commit()
        print(f"✅ {Table1}表成功插入 {rows_inserted} 条记录!")

    # 关闭游标和连接
    cursor.close()
    connection.close()
    print("-" * 50)
    print("✅ 所有测试通过!")

except cx_Oracle.DatabaseError as e:
    error_obj, = e.args
    print(f"❌ 数据库错误: {error_obj.code} - {error_obj.message}")
except Exception as e:
    print(f"❌ 连接失败: {e}")

第二步

通过业务关系分析和这些表有关的一些交互操作或spark作业,也可从代码中查询和创建数据库连接接口有关的工程,分析这些工程中对应的功能操作。

sql 复制代码
--V$SESSION 是 Oracle 动态性能视图。按会话的 MODULE(模块名)分组,统计每个模块当前有多少个数据库会话,并按会话数从多到少排序。
SELECT count(*) AS cnt , MODULE FROM V$SESSION GROUP BY MODULE ORDER BY CNT  DESC;

--查询当前 Oracle 实例中,非后台会话、客户端程序名以 java@ 开头、并且其 MODULE 属于"包含 java 且会话数大于 1"的模块,(**java的一般是计算进程**)
--并列出这些会话的客户端机器、客户端进程、服务器进程、上一个 SQL ID / 当前 SQL ID / 上一个 SQL 文本、模块名,并按登录时间倒序排列。
SELECT
    s.machine,
    s.program,
    s.process AS client_pid,
    p.spid AS server_spid,
    s.prev_sql_id,
    s.sql_id,
    q.sql_text,
    s.module
FROM v$session s
JOIN v$process p ON s.paddr = p.addr
LEFT JOIN v$sql q 
    ON s.prev_sql_id = q.sql_id 
    AND s.prev_child_number = q.child_number
WHERE s.type <> 'BACKGROUND' and s.program like 'java@%' AND s.module IN (
        SELECT MODULE
        FROM v$session
        WHERE MODULE LIKE '%java%'
        GROUP BY MODULE
        HAVING COUNT(*) > 1
  ) ORDER BY s.logon_time DESC;

当提交spark作业后,后台数据库监控第二个sql执行结果(通过python实现实时监控),当会话数大于1时,记录下执行的sql。建议多节点执行spark作业并记录下来sql语句是发生在driver节点还是executor节点,便于研发定位问题,查询结果如下图示例:

数据库性能分析的其它sql:

sql 复制代码
--当前数据库中活跃会话的总数量,用于快速评估数据库当前的实时并发负载压力
SELECT count(*) FROM v$session WHERE status = 'ACTIVE';

--查询当前数据库中所有活跃的非后台用户会话及其正在执行的SQL语句详情(包括SQL文本、登录信息、程序来源等),用于实时监控数据库的当前操作负载
SELECT 
s.sid, s.serial#,
s.username, 
s.status,
s.sql_id, 
s.prev_sql_id,
q.sql_text,
s.program,
s.machine,
s.logon_time
FROM 
v$session s
LEFT JOIN 
v$sql q ON s.sql_id = q.sql_id
WHERE 
--s.status = 'ACTIVE' AND    -- 筛选活跃会话
s.type != 'BACKGROUND'  -- 排除后台进程
AND s.sql_id IS NOT NULL;

--查询指定SQL_ID(cm5vu20fhtnq1)在历史中的每次活跃会话采样记录,包括执行时间、客户端信息、应用模块等上下文,用于追溯该SQL的历史性能问题或排查谁在何时执行过它。
SELECT
    c.username,          -- 数据库用户名
    a.SAMPLE_TIME,       -- 采样时间,帮你定位高峰期
    a.MODULE,            -- 应用模块名,非常有用的线索
    a.ACTION,            -- 模块下的动作
    a.PROGRAM,           -- 连接的程序名,比如 JDBC Thin Client
    a.MACHINE,           -- 客户端机器名
    a.SQL_EXEC_START     -- SQL执行开始时间
FROM
    DBA_HIST_ACTIVE_SESS_HISTORY a,
    DBA_HIST_SQLTEXT b,
    DBA_USERS c
WHERE
    a.SQL_ID = 'cm5vu20fhtnq1'   -- 替换为第一步查到的SQL_ID
    AND a.SQL_ID = b.SQL_ID(+)
    AND a.USER_ID = c.USER_ID
ORDER BY
    a.SAMPLE_TIME DESC;

--以下这两段SQL是Oracle数据库中排查锁问题的经典组合,分别从"谁在等谁"和"锁住了什么对象"两个维度入手:
-- 签署锁的持有者(Holder)和等待者(Waiter)
SELECT DECODE(l.request, 0, 'Holder:', 'Waiter: ') || s.sid || ',' || s.serial# sess,
       l.id1,
       l.id2,
       l.type,
       l.lmode,
       l.request,
       s.username,
       s.sql_id,
       s.event
  FROM v$lock l, v$session s
 WHERE (l.id1, l.id2, l.type) IN (SELECT id1, id2, type FROM v$lock WHERE request > 0)
   AND l.sid = s.sid
 ORDER BY l.id1, l.ctime DESC, l.request;
--查看被锁定的具体对象
SELECT lo.session_id, lo.oracle_username, ao.object_name, lo.locked_mode FROM v$locked_object lo, dba_objects ao WHERE ao.object_id = lo.object_id;
相关推荐
滕州市燕猫虎计算机科技工作室个体工商户1 小时前
MySQL、MVCC、多版本并发控制
数据库·mysql·mvcc·数据库事务
明航咨询-陈老师1 小时前
ITSS运行维护服务能力成熟度认证技术纵深:标准模型、等级路径、2026审核趋势与CS/CMMI对比
服务器·数据库·cmmi
缓慢更新2 小时前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
AI小百科2 小时前
向量数据库:AI 的「记忆仓库」是怎么工作的
数据库·人工智能·oracle
煎饼皮皮侠2 小时前
【设计】设计一个Web版数据库管理平台(之七):多数据库类型易扩展
数据库
Nturmoils2 小时前
MongoDB迁移之后,Spring Data 和 Hibernate 各自接哪类请求
数据库
画中有画3 小时前
在自动化脚本中操作本地数据库
数据库·oracle·自动化
Decay__3 小时前
09_MySQL 闪回与时间点恢复 —— binlog 回放、mysqlbinlog、PITR 与误删恢复
运维·数据库·sql·mysql·架构
太理摆烂哥3 小时前
MySQL用户管理
数据库·mysql