归档日志存在arch_深度解读:归档空间不足导致的数据库无法登录问题

abd3eba82f422c4cde13dafa13cc6a1e.png

有一天接到了同事的一个电话,说是有一个数据库无法访问了,希望我帮一下忙,连接过去查看,发现是一个看似很简单的ORA错误,如下。

$ sqlplus / as sysdba

Copyright (c) 1982, 2011, Oracle. All rights reserved.

ERROR:

ORA-09817: Write to audit file failed.

Linux-x86_64 Error: 28: No space left on device

Additional information: 12

ORA-01075: you are currently logged on

这种问题想必大家都或多或少碰到过,从错误日志来看还是因为审计日志写不进去了;再进一步来说,就是磁盘空间不足了。

通过df -h的结果足以说明,磁盘空间确实是不足了,如下。

Filesystem Size Used Avail Use% Mounted on

/dev/sda7 5.9G 633M 4.9G 12% /

...

/dev/sdb1 3.1T 3.0T 0100%/data

注意:如果数据库因为磁盘空间无法登录,查看不了审计日志的路径,可以通过$ORACLE_ HOME/dbs下的参数文件来查找审计日志的路径。

准备清理磁盘空间,发现有一个大约100MB的临时文件,可以先挪到其他的目录下,然后再次尝试TNS连接就没有问题了。

问题似乎已经得到初步解决。但是过了不到一分钟,再次尝试,发现又无法登录。查看磁盘空间,空间已经用完了,于是又做了一些磁盘空间的清理,问题的处理才暂时告一段落。

这样一来,我们需要分析问题的原因。

首先,空间问题导致的数据库无法登录是不应该犯的错误。因为查看前几天的巡检结果,看到还剩下很多的空间。按照一个阈值来参考,还是够用的。

那就说明数据库层面还是有一些异常的地方,于是得到了如图4-2所示的报告。这个报告能够看出一个数据库的负载情况,能够看到在一个小时内redo的切换频率。横轴上方是时间,显示的是每个小时的归档切换频率,纵轴是日期。

可以看到在问题发生的时间段内(用框图标注出来的部分),redo切换频率极高,数据库负载是在近两天才升上去的,但是数据库redo切换如此频繁,是否在应用层面有一些大的变更目前还没有相关的通知,而导致空间问题就这样累计了下来,结果到第二天归档时一下子撑满了磁盘空间才发现问题。

13bbcb3f1ae1a8b50b1cf20f8e2337dc.png

为证实上面的想法还需要协同其他部门进一步确认,在此不作赘述。但是对于DBA来说,确实需要检查数据库层面的一些数据变化情况,而随时做出响应。

因为目前的环境使用Data Guard的架构,归档数据传输到备库的频率还是很高的,所以对于归档的保留也就采用了一些处理。目前的归档保留时间是2天,考虑到这些天内归档切换频率极高,很可能备库的空间也会占满。所以简单地修改了一下crontab中归档的删除策略很有必要。

注意:归档路径最好是放在fast_recovery_area_dest下,在11g备库中,会有一个空间阈值,超过了80%会自动删除闪回区下的文件,这是11g的一个新特性。

对于这个问题的反思如下:

(1)对于归档的删除,最好能够做些前瞻性的处理,比如,对于归档产生较多,但是又不希望直接删除归档的情况,可以对归档进行定时压缩和定时删除(定时删除的文档须是过期的),这样既节省了空间又可保留尽可能多的归档。

(2)数据库级的变更和应用关系极为紧密,如果有什么大的变更或者批量处理还是能够让DBA知晓,在这个问题上DBA还是需要做到先知先觉。

(3)从数据库层面进行了分析,在短期内生成了大量的redo,造成了频繁的日志切换,导致归档占用了大量的空间,最后无法登录,因此,我们可以做一些工作来尽可能长时间的保留近期的归档;同时我们还可以换一个思路,即查看是什么操作生成了大量的redo,是否可以减少redo的生成量,达到釜底抽薪的效果。

关于上面的反思第三条,顺着这个思路我们详细讲述一下。

一般来说,日志会记录尽可能完整的信息,这是做数据恢复的基础,但谨慎起见,我们先来分析一下再来做决定看看是否可行。

查看数据库的redo切换频率,在近几天内的redo切换频率极高,基本每个小时日志切换都在250次左右。对于一个OLTP的系统来说是非常高的负载,这种频繁的日志切换我也只在数据迁移的一些场景中碰到过。

但是奇怪的是查看数据库的DB time,却发现这个值其实并不高,如下所示,看起来似乎前后矛盾,因为从这一点来看数据库内的负载变化其实并不是很高。

BEGIN_SNAP END_SNAP SNAPDATE DURATION_MINS DBTIME

---------- ---------- ----------------------- ----------

82560 82561 05 Sep 2015 00:00 30 26

82561 82562 05 Sep 2015 00:30 30 26

82562 82563 05 Sep 2015 01:00 29 29

82563 82564 05 Sep 2015 01:30 30 27

82564 82565 05 Sep 2015 02:00 30 23

82565 82566 05 Sep 2015 02:30 30 23

82566 82567 05 Sep 2015 03:00 30 20

对于这种情况,我们还是抓取一个AWR报告来看看。

在AWR报告中,可以看到瓶颈还是主要在DB CPU和IO相关的等待事件,见表4-1。

Top 5 Timed Foreground Events

e9c8b044966cd8cfd0d8f874e40b9049.png

查看时间模型,可以看到DB CPU和SQL相关的影响各占了主要的比例。

查看等待事件能够看到主要都是在CPU的消耗上,进一步分析能够关注的重点就是SQL语句,Top 1的SQL语句执行情况见下表。

bd8527dcc4370d294af8ca7ff48a5b70.png

这条语句执行频率极高,语句也很简单,但是CPU消耗却很高,初步怀疑是走了全表扫描。

语句如下:

update sync_id set max_id = :1 where sync_id_type = :2

简单查看执行计划,发现确实是走了全表扫描;通常情况下,这种情况首先是需要走索引的,没有索引可以新建一个索引,但是当笔者看到SQL by Executions这个部分时,发现问题其实不是那么简单。

可以看到第2个语句就是刚刚提到的Top 1的SQL,对应的指标很不寻常的,一次执行处理的行数近5 000多行,执行了1万多次,处理的数据行数近8000万,见下表。

3cf6d8bbf0cdd66fbb1f5c0e483808c8.png

但是查看表,发现数据其实就是1万多条,所以这明显是一个问题。

我们再来进一步分析,一个小表1万多行的数据,每次执行更新5 000多行,可以断定数据的分布是不均匀的。因为这个表结构非常简单,只有两个字段,所以还是很好定位的。

简单查看了一下数据情况,发现数据主要分布在两个type列值上,基本上占用了99.99%以上,如下所示。

SQL> select max_id,count(*)from SYNC_ID where SYNC_ID_TYPE='SYNC_LOG_ID' group by max_id;

MAX_ID COUNT(*)

---------- ----------

38 5558

SQL> select max_id,count(*)from SYNC_ID where SYNC_ID_TYPE=SYNC_TEST2_LOG_ID' group by max_id;

MAX_ID COUNT(*)

---------- ----------

108 5577

从数据的分布情况可以看到,表中存在了大量的冗余数据,而且表中也没有索引字段和其他约束;这样一来,每次更新时只要更新一个字段值,就会修改5 000多行数据的值;如果执行频繁,短时间内就会频繁生成大量的redo。因此从目前的SQL运行情况来看,这条语句应该是造成redo频繁切换的主要原因。

毕竟是线上环境,需要做一些确认和沟通之后才能够变更的,目前只是建议,我们还需要验证测试一下。

测试的思路很简单,只需把这个表里的数据导出来,放到其他的测试环境中,然后模拟做频繁的更新,查看归档的频率即可。

首先把数据导入另外一个测试环境中。

其次使用下面的语句进行频繁更新即可,先更新100万次,中间可以随时中断,于是我写了下面的脚本。

function test_update

{

sqlplus test/test <<EOF

update sync_id set max_id = 38 where sync_id_type = 'SYNC_LOG_ID';

commit;

EOF

}

for i in {1..1000000}

do

test_update

done

在测试开始的时候,归档切换频率是0。

Redo Switch times per hour xxxx-Sep-05 16:02:55

MON DA 16 17 18 19 20 21 22 23

--- -- -- ---- ---- ---- ---- ---- ---- ---- ----

09 05 0 0 0 0 0 0 0 0

运行了不到3分钟,日志切换就达到了14次,还是能够说明问题的。

Redo Switch times per hour xxxx-Sep-05 16:05:20

MON DA 16 17 18 19 20 21 22 23

--- -- - ---- ---- ---- ---- ---- ---- ---- ----

09 05140 0 0 0 0 0 0

然后我们使用更新的方式来验证一下。

Redo Switch times per hour xxxx-Sep-05 16:08:04

MON DA 16 17 18 19 20 21 22 23

--- -- ------ ---- ---- ---- ---- ---- ---- ----

09 05140 0 0 0 0 0 0

过了4分钟,日志一次都没有切换,这就足以说明了我们的推论是正确的。

MON DA 16 17 18 19 20 21 22 23

--- -- ------ ---- ---- ---- ---- ---- ---- ----

09 05140 0 0 0 0 0 0

最后就是做进一步的确认,然后在正式的环境中部署,在线上环境清理了冗余数据之后,这个问题再没有出现过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
帮我把以下数据变成json格式:{ "switch_Cash": "Y", "pageMark": "add", "tx_date": "20230305", "cur_no": "1", "sfk_type": "03", "lease_type": "经营租赁", "change_rate": "0", "cap_name": "20220731SYZC000271", "lease_no": "20220731SYZC000271", "contract_key": "6980120220731001", "contract_name": "测试合同20220731-01", "bef_arch_area": "300", "bef_cash_rate: 2.38, "bill_type: 3, "bef_tax_rate: 5, "sfk_term: 4, "bef_tot_pay_time: 2, "bef_eve_amt: 22500, "exe_renew: N, "bef_renew_amt: 0, "bef_renew_eve_amt: 0, "bef_tot_pay_amt: 19047.62, "bef_unset_fin_exp: 221.39, "bef_contract_amt: 45000, "sige_date: 20220731, "bef_arch_position: 广州省佛山市宝芝林, "bef_effect_date: 20220801, "bef_mtr_date: 20240730, "bef_first_fk_date: 20220731,, "bef_renew_eft_date: , bef_renew_mtr_date: , aft_arch_area: 300, aft_bill_type: 3, aft_tax_rate: 5, aft_levy_rate: 5, aft_cash_rate: 2.38, aft_sfk_type: 03, aft_exe_renew: N, is_onchange: N, aft_sfk_term: 4, aft_contract_amt: 45000.00, aft_tot_pay_time: 2, aft_eve_amt: 22500, bef_renew_tot_pay_time: 0, max_term_seqn: 0, aft_effect_date: 20220801, aft_mtr_date: 20240730, aft_first_fk_date: 20220731, aft_renew_eft_date: , aft_renew_mtr_date: , bef_levy_rate: 5, cap_code: fjr0901, lease_no1: 20220731SYZC000271, aft_tot_pay_amt: 42857.14, aft_unset_fin_exp: 184.48999999999796, apply_amt: 23809.52, remark: test0609, change_valid_date: 20230609, cap_name_zh_: 测试资产-20230731-01, cur_no_zh_: 人民币, sfk_type_zh_: 周期性, flowable_: 1, flowable_targetNodeData: {"category":"CWSYS_69","isInput":"1","menuName":"使用权资产变更","pageNo":"cwsys_05_07"}, flowable_file_dataInfo: {"flowable_file_storeType":"undefined","flowable_file_split":false,"flowable_file_canDelete":true,"flowable_file_readOnly":false,"flowable_file_id":"FL-495eabb0-069c-11ee-9b92-59e9b66c35e6"}, cashList: [{"contract_no":"20220731HTXX000001","pay_date":"20220731","no":"20230201XJL000031","pay_amt":"25000.00","term_start_date":"20220801","create_trace_no":"16","tx_date":"0","trace_no":"0","term_end_date":"20230731","pay_sts":"未支付","version":"1","tax_rate":"0.00","term_seqn":"1","tax_amt":"1190.48","pay_sts_val":"0","id":"1","create_date":"20230201","levy_rate":"0.00"},{"contract_no":"20220731HTXX000001","pay_date":"20230731","no":"20230201XJL000032","pay_amt":"20000.00","term_start_date":"20230731","create_trace_no":"16","tx_date":"0","trace_no":"0","term_end_date":"20240730","pay_sts":"未支付","version":"1","tax_rate":"0.00","term_seqn":"2","tax_amt":"952.38","pay_sts_val":"0","id":"1","create_date":"20230201","levy_rate":"0.00"}] }
最新发布
06-13

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值