Skip to content

浅谈关于清理oracle监听log的方式以及考虑

listener log是一个比较有意思的东西,作为日常运维的一个点,多数的dba都知道清理的方式就是定期备份清下,而这小点子细挖下去会发现还是有些意思的。这里介绍几种日常的清理监听日志的方式以及关注点,我的观点是在做这方面清理的时候,日志有必要制定一个备份策略。

1.offline listener清理
这种方式主要是在停掉了监听或者直接停掉了业务数据库后,对listener.log进程mv或者backup的操作后新建listener.log,或者就是以清理文件内容的方式进行清理。

2.online listener清理
这种清理可以理解为在不影响业务的情况下清理log,这个以oracle角度来区分,区别在于是否禁止listener进程持续写日志上,关闭listener写日志命令如下:

LSNRCTL> set current_listener
LSNRCTL> set log_status off
--之后备分listener.log,清除log后恢复listener进程的日志记录,
LSNRCTL> set log_status on

那么这里在清除log的系统命令上有多种,这里介绍下linux下的3种以及windows上的1种

linux/unix平台:

2.1 cat /dev/null > 要清空的文件
例:

cat /dev/null > /u01/oracle/product/db/network/log/listener.log

2.2 echo “” > 要清空的文件
例:

echo "" > /u01/oracle/product/db/network/log/listener.log

2.3 cp /dev/null 要清空的文件
例:

cp /dev/null /u01/oracle/product/db/network/log/listener.log

以上三种清理都支持在线直接清理日志,可以不禁止listener进程持续写日志的情况下直接执行,只是在考虑点上在前面所说的是否禁止listener进程持续写日志。我日常使用2.1的方式,从系统效率上cp /dev/null的方式会优于其他2种。

Windows平台

2.4 @echo.> 要清空的文件
例:

@echo.> D:\oracle\listener.log

3.rename file方式清理

这个方法在10g之前的版本可以使用,在11g由于adr的设置需要禁止adr后才能够使用,否则会遭遇“TNS-01251: Cannot set trace/log directory under ADR”的错误。
登陆listener控制台,命令如下:

LSNRCTL>set current_listener LSNRCTL>set log_file
LSNRCTL>save_config

例:

LSNRCTL>set current_listener LISTENER1
LSNRCTL>set log_file listener1_1.log
LSNRCTL>save_config

当执行完set log_file这个命令后,系统更新listener.ora文件,同时生成新的listener日志,此后就可以对老的listener.log进行处理。这种方式在sun的solaris蹭遭遇过bug导致监听进程offline,所以使用时候注意平台。还有一个注意点就是在多个监听下分别对每个监听的日志进行清理时候需要分开执行,因为save_config会覆盖当前设置之前的其他监听的设置,导致前面的设置失效。

接连遭遇2波问题都是oracle hang

祸不单行.
1.故障1
半夜收到wang.rui电话,数据库hang住了一样,所有的redolog都是active,新加redo马上就会写完变成active状态,无论多大.
思路:
判断数据库是不是还活着,hang analyze.或者看归档的切换频率,检索告警看看有没有价值的信息
这类东西能让redo这么繁忙,一般都是大事务或者并发大事务,所以可以挖下归档看看操作
既然有观点2了,那么job和schedul是跑不掉检查的
看看数据库的等待事件以及session block情况(别问我为啥要看阻塞,嘿嘿)

故障1最终话费了大概前后几分钟,检测出来,是由于大事务被撤销,产生大量回滚,同时oracle产生了128个并行进程在恢复.这与参数fast_start_parallel_rollback有关,默认为low.由于大量并行的恢复,导致io瓶颈的产生,同时undo争用厉害,改为high是不行了,改为false后,所有开销马上下降.当然这里存在了一个疑问点,默认是low的情况下并行进程是数量应该是cpu_count*2,应该为64才对,为啥我这里128??

2.故障2
清早收到数据库进程阻塞故障,原因不明,所有进程hang住.10205版本数据库linu平台.

检测发现cpu耗尽,内存耗用光,采集了一些os信息后重启恢复了系统,检测后来的信息发现有css的等待,数据库为单机,未采用grid,比较奇怪,跟踪后发现类似bug,Bug 10024824.怀疑大量session因为此bug被hang住把cpu耗光了….主要是发现oracle也没啥很异常的sql波动…准备打补丁.

Oracle full table scan 的跟踪监视

最近一个客户的数据库反应不定时的性能问题,经过跟踪发现是一系列的全表扫相关SQL,其中还碰到了比较诡异的全表扫都是顺序读的情况.和周亮以前也讨论过此类情况只是当时这方面的事情并没有太多的眉目,这次跟踪发现了是和undo一致性读有关,还存在大量的row chains.当然这里不讨论这个case,这个case可能会在新书中描述.这个文章不描述具体的原理,只是作为一个对数据库全表扫相关信息收集诊断建议.

在跟踪某一特定的事件时候,有时候没有监控系统或者其他相关捕获信息的手段,则诊断起来比较耗时间,比如跟踪系统中全表扫的情况,默认情况下是只能获取当时时刻具体的情况,这里介绍通过AWR记录中来获取相关的信息,由于AWR从v$sql里面获取的sql是有条件限制的,因此该方法并不能补全数据库中所有的全表扫相关sql(其他情况也是),因为awr收集sql的情况是以statistics_level 的设置为依赖,typical(top 30)或者all(top 100)收集的top sql信息不同.

 

1.周期的全表扫信息

col c1 heading "Day|Hour" format a20
col c2 heading "Full TABLE scan|Count" format 999,999
BREAK ON c1 skip 2
BREAK ON c2 skip 2
SELECT TO_CHAR(sn.begin_interval_time,'hh24') c1,
COUNT(1) c2
FROM dba_hist_sql_plan p,
dba_hist_sqlstat s,
dba_hist_snapshot sn,
dba_segments o
WHERE p.object_owner <> 'SYS'
AND p.object_owner = o.owner
AND p.object_name = o.segment_name
AND o.blocks > 1000
AND p.operation LIKE '%TABLE ACCESS%'
AND p.options LIKE '%FULL%'
AND p.sql_id = s.sql_id
AND s.snap_id = sn.snap_id
GROUP BY TO_CHAR(sn.begin_interval_time,'hh24')
ORDER BY 1;

查询结果类似如下:

Large Full-table scans Per Snapshot Period
Begin
 Interval FTS
 time Count
 -------------------- --------
 04-10-18 11 4
 04-10-21 17 1
 04-10-21 23 2
 04-10-22 15 2
 04-10-22 16 2
 04-10-22 23 2
 04-10-24 00 2

2.每小时的全表扫信息

col c1 heading "Day|Hour" format a20
col c2 heading "Full TABLE scan|Count" format 999,999
BREAK ON c1 skip 2
BREAK ON c2 skip 2
SELECT TO_CHAR(sn.begin_interval_time,'hh24') c1,
  COUNT(1) c2
FROM dba_hist_sql_plan p,
  dba_hist_sqlstat s,
  dba_hist_snapshot sn,
  dba_segments o
WHERE  p.object_owner <> 'SYS'
AND p.object_owner                                    = o.owner
AND p.object_name                                     = o.segment_name
AND o.blocks                                          > 1000
AND p.operation LIKE '%TABLE ACCESS%'
AND p.options LIKE '%FULL%'
AND p.sql_id  = s.sql_id
AND s.snap_id = sn.snap_id
GROUP BY TO_CHAR(sn.begin_interval_time,'hh24')
ORDER BY 1;

查询结果类似如下:

Large Table Full-table scans
Averages per Hour

Day                       FTS
Hour                    Count
-------------------- --------
00                          4
10                          2
11                          4
12                         23
13                         16
14                          6
15                         17
16                         10
17                         17
18                         21
19                          1
23                          6

3.基于星期的全表扫信息

col c1 heading "Week|Day" format a20
col c2 heading "Full TABLE scan|Count" format 999,999
BREAK ON c1 skip 2
BREAK ON c2 skip 2
SELECT TO_CHAR(sn.begin_interval_time,'day') c1,
  COUNT(1) c2
FROM dba_hist_sql_plan p,
  dba_hist_sqlstat s,
  dba_hist_snapshot sn,
  dba_segments o
WHERE  p.object_owner <> 'SYS'
AND p.object_owner                                    = o.owner
AND p.object_name                                     = o.segment_name
AND o.blocks                                          > 1000
AND p.operation LIKE '%TABLE ACCESS%'
AND p.options LIKE '%FULL%'
AND p.sql_id  = s.sql_id
AND s.snap_id = sn.snap_id
GROUP BY TO_CHAR(sn.begin_interval_time,'day')
ORDER BY 1;

查询结果类似如下:

Week                      FTS
Day                     Count
-------------------- --------
sunday                      2
monday                     19
tuesday                    31
wednesday                  34
thursday                   27
friday                     15
Saturday                    2

以上脚本作者为Donald K. Burleson.
我对此脚本做了些变更,除了生成html格式外额外加入索引类的信息,变更的脚本未在blog上发布.