审计表过大数据库弄卡顿

2024年 7月 3日 46.6k 0

问题描述

刚刚领导打电话让赶紧停下手里的任务,远程分析XX省的核心库,该库正处于hang死的状态,业务卡顿的无法操作。由于现场服务器连接复杂,现场同事五六分钟没连上,时间紧,就先通过数据库连接工具分析排查。

分析过程

服务器运行情况

由于连不上服务器,业务急需恢复,该步骤暂时跳过。

nmon -->io情况  cpu情况

  • cpu高  一般为逻辑读高,不排除有些异常的逻辑读sql

工具 描述
uptime 平均负载
vmstat 包括系统范围的cpu平均负载
mpstat 查看所有cpu核信息
top 监控每个进程cpu用量
sar -u 查看cpu信息
pidstat 每个进程cpu用量分解
perf cpu剖析和跟踪,性能计数分析 需安装

  • I/O高  一般为物理(磁盘)读高,可能有全表扫等

工具 描述
iostat 磁盘详细统计信息
iotop 按进程查看磁盘IO的使用情况 需安装
pidstat 按进程查看磁盘IO的使用情况
perf 动态跟踪工具

  • 内存高 sga(buffer cache、share pool等) ,pga分配内存问题等

工具 描述
free 缓存容量统计信息
vmstat 虚拟内存统计信息
top 监视每个进程的内存使用情况
pidstat 显示活动进程的内存使用统计
pmap 查看进程的内存映像信息
sar -r 查看内存
dtrace 动态跟踪
valgrind 分析程序性能及程序中的内存泄露错误

查看进程和会话参数设置

经查询,进程数和会话数均未超过参数设置值,排除进程和会话数过多的原因。

锁表也有可能是连接数不够。

--查看当前的数据库连接数
select count(*) from v$process;
返回187

--查看数据库允许的最大连接数
select value from v$parameter where name ='processes';
返回3000

--查看当前的session连接数
select count(*) from v$session;
返回168

--查看当前并发连接数
select count(*) from v$session where status='ACTIVE';
返回120

--查看数据库允许的最大会话数
select value from v$parameter where name ='sessions';
返回4884

假设超过参数设置值,进行以下修改:

--修改数据最大连接数
alter system set processes = 500 scope = spfile;
--重启关闭数据库
shutdown immediate;
startup;

拿到锁表sql

从sql方面进行排查,如果是select 的锁可以释放,delete需和业务确认后后再决定释放与否。

查看是否有锁表

该查询花费了将近5分钟,输出9781条记录.

set lines 999 pages 999
col object_name for a30
col machine for a30
SELECT object_name, machine, s.sid, s.serial#
FROM gv$locked_object b, dba_objects o, gv$session s WHERE b.object_id=o.object_id
AND b.session_id = s.sid;

返回结果中有大量object_name为AUD$的记录。和现场确认说是现场有三级等保要求必须开启审计功能。

查看具体的锁表sql

由于查询时间长暂时放弃查询锁表语句对应 的sql

select l.session_id sid,
s.serial#,
l.locked_mode,
l.oracle_username,
s.user#,
l.os_user_name,
s.machine,
s.terminal,
a.sql_text,
a.action
from v$sqlarea a, v$session s, v$locked_object l
where l.session_id = s.sid
and s.prev_sql_addr = a.address
order by sid, s.serial#;

SELECT O.OBJECT_NAME,
S.SID,
S.SERIAL#,
s.LOGON_TIME,
'alter system kill session ' || '''' || S.SID || ',' || S.SERIAL# || ''';'
FROM V$LOCKED_OBJECT T, ALL_OBJECTS O, V$SESSION S
WHERE T.OBJECT_ID = O.OBJECT_ID
AND T.SESSION_ID = S.SID;

释放数据表锁

本想杀掉审计的会话,但是雨哥说开启审计功能的场景下,即使批量杀掉审计的会话还是不断的会有新的审计会话生成。因此放弃释放数据表锁,采用后面的查询审计表大小并清空审计表的解决办法。

// 释放SESSION SQL:
alter system kill session 'sid, serial#';
ALTER system kill session '23, 1647';

//如果上述语句杀不掉提示会话不存在,尝试该语句
alter system disconnect SESSION '399, 14608' immediate;

//
遇到杀不掉的进程,可以根据SID,查找系统中对应的spid,然后kill -9 spid杀掉
select p.spid, s.osuser, s.program
from v$session s,v$process p
where s.paddr=p.addr and s.sid=12345
操作系统上操作 (慎重)
ps -ef | grep 上面的spid
kill -9 上面的spid

查询审计表大小

--查总记录数
select count(*) from sys.aud$
count
-------
53005448

--查看物理大小
select round(sum(bytes) / 1024 / 1024 / 1024, 2) || 'G'
from dba_segments
where owner ='SYS' and SEGMENT_NAME='AUD$'

查看集群状态

现场同事终于连上了服务器,在查看审计表大小等待的过程中,由于时间长,等待过程中查了下集群状态,3个节点只剩了1个节点,慌的一批。

su - grid
crsctl stat res -t

审计表过大数据库弄卡顿-1

可能原因:节点1负载高,节点2和节点3依然活着,但是节点间状态探测失败。

解决办法

终止查看物理大小会话

关闭数据库连接工具的查询会话

清空审计表

非常幸运的是现场同事终于连上了服务器

查看物理大小 步骤跳过,执行了将近10分钟未出结果,恢复业务第一,中断查询物理大小直接进行清空审计表操作。

--清空审计表
sqlplus / as sysdba
TRUNCATE TABLE SYS.AUD$;

审计表过大数据库弄卡顿-2

另新打开一创建再次执行清空审计表操作

--清空审计表
sqlplus / as sysdba
TRUNCATE TABLE SYS.AUD$;

所幸清空审计表操作成功。联系现场测业务,业务恢复正常。

补充:

如果清空审计表依然报错,就再开个窗口,一个truncate,另一个kill aud$相关的session(别kill truncate语句的session)

查看集群状态

集群恢复正常。

su - grid
crsctl stat res -t

审计表过大数据库弄卡顿-3

总结

和现场建议配置审计定期清理,但是沟通后领导不愿意,定时任务暂时搁浅,将步骤发给现场,定期手动执行清空审计表操作。

附录

创建定时任务,定期清理AUD$表

创建定时任务,定期清理AUD$表  sys用户procedure

--sys用户登录 创建存储过程
export ORACLE_SID=orcl
sqlplus / as sysdba
create or replace procedure sp_trunc_audit_log is
begin
execute immediate
'truncate table aud$';
end;
/

授权system用户执行该存储过程的权限
grant execute on sp_trunc_audit_log to system;

--system用户创建procedure
切换到system用户
conn system/oracle
create or replace procedure sp_job_trunc_audit_log is
begin
sys.sp_trunc_audit_log;
end;
/

--system用户 自动调度job
sqlplus / as sysdba
切换到system用户
conn system/oracle
BEGIN
DBMS_SCHEDULER.CREATE_JOB
(
job_name => 'day_trunc_audit_log',
job_type => 'STORED_PROCEDURE',
job_action => 'SP_JOB_TRUNC_AUDIT_LOG',
start_date => sysdate,
repeat_interval => 'FREQ=DAILY; BYHOUR=04; BYMINUTE=05;INTERVAL=1',
enabled => true,
comments => 'every day truncate table audit log'
);
END;
/

说明:
FREQ=DAILY指定按日重复,byhour指定几点,byminute指定几分,bysecond指定几秒, INTERVAL=1 间隔1天

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论