ADG连环排坑实战,希望你别遇到

老马也有失蹄时,万万没想到,这次当了一回“头痛医头,脚痛医脚”的庸医。先来介绍下这次当庸医的情况吧:客户的一套三节点的RAC,上线了三年时间,随着业务量越来越大,数据库运行越来越慢。客户为了缓解特殊时间段的业务促销压力,决定搭建一套单机的ADG来分摊原生产库上的一部分查询压力。

▲ Data Guard架构

由于业务的实时性较高,ADG配置采取了LGWR和ASYNC的模式来进行Redo变化的传输。在搭建环境之后的第二天,一个只读查询业务便迁移了过来。该业务的特点是并发高,实时性要求高。由于上线比较仓促,业务刚迁上去2-3天之内相继出现了不少问题,并且数据库还连续宕机了几次。面对问题,我们是出现一个处理一个,但这种被动式的处理方式非常低效。

我们先来看看都出现了哪些问题。

问题1 监听连接问题

当把一个只读业务迁移之后,监听出现大量的短连接冲击,出现一些TNS错误。

1、操作系统参数设置过低,导致资源不足

这里的错误主要是Linux Error: 11: Resource temporarily unavailable,需要通过调整操作系统参数nproc来解决。在Redhat/CentOS 7的系统中调整位置发生了变化,修改指定用户的nproc在/etc/security/limits.d/20-nproc.conf文件中配置,可参考官方文档:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/migration_planning_guide/sect-red_hat_enterprise_linux-migration_planning_guide-system_management

sed -i 's/4096/131072/g' /etc/security/limits.d/20-nproc.conf

不过还要注意一点,当你调整了nproc,也不一定能达到它最大的值。这是由于内核参数pid_max设置过小导致的,还需要把kernel.pid_max参数设大一点。

vi /etc/sysctl.conf
kernel.pid_max = 131072

2、监听短链接并发过高,出现连接Refuse和Timeout

这里最常规的优化方法是改成长链接。但是由于历史原因没办法修改,所以还是从监听本身着手。

第一种是设置RATE_LIMIT,如图所示,当限制为每秒3个时,同时并发连接超过3个就会报错。这种方法起到高并发连接的限制作用,超出了限制就会报错。而业务程序基本上每秒就超过100个并发连接,同时这些连接需要取最新实时的数据。我们就是为了让并发连接不报错。因此设置RATE_LIMIT参数并不符合要求。

第二种是在监听中增加QUEUESIZE参数,QUEUESIZE参数是指监听器在建立连接时可以存储的并发连接请求数。如果传入请求数超过缓冲区大小,则请求连接的客户端将接收失败。在比较理想的情况下,此缓冲区大小应该等于或者大于预期并发请求的最大数量。Oracle官方文档也提到了这个参数适用于处理大量并发连接的请求。

在CentOS7平台我们可以通过strace命令查看默认的QUEUESIZE参数。

strace -fo /tmp/queue.log lsnrctl start listener
[root@oracle-002 ~]# cat /tmp/queue.log | grep -i "listen("
90066 listen(14, 128)=0

可以看到在cenot7和11g数据库版本中默认是128,我们把这个设置成512。

问题2 ADG数据库出现大量的library cache lock和ORA-00600错误

我们安装了和主库相同的PSU,但是在运行的过程中数据库仍然会出现大量的library cache lock和ORA-00600[kgllkde-bad-lock]及ORA-00600[kss_get_type: bad control]等错误。可以通过安装单独的patch 24385983 18515268、19180394、17608518等来增强数据库的健壮性。

针对在ADG数据库上出现的library cache lock,我们做了单独的补丁分析,参考了文档WAITEVENT: “library cache lock” Reference Note (Doc ID 34578.1),如下excel列表所示,相关和容易触发问题的补丁都做了安装。

这里有几个小技巧的分享:

首先这里的一些bug是特殊操作才会触发的,例如添加interval partition分区。而数据库中根本没使用到interval的分区,所以这类Bug就不会触发。

其次Prob列代表触发的概率,分为I,II,III,IIII等等,IIII是触发几率最高的。而I,II是触发几率最低的,这种触发较低的补丁可以考虑不安装。毕竟为了一个极低的概率去安装一些补丁获取的收益不大(除非这个极低的概率一直会触发)。

最后就是NB列。NB代表安装了补丁,还需要做一些设置才能enable它的功能,例如设置event事件(注意:如果不设置事件或者相关参数,安装了补丁也不起作用)

问题3 Centos7操作系统cache回收问题

通过观察操作系统我们发现当free内存值下降之后,系统会触发文件系统cache回收动作,这些动作会让system cpu变高。往往会造成主机hang住没办法操作。系统当前的vm.dirty_background_ratio和vm.dirty_ratio参数设置的是平衡模式,一般推荐使用这个方案。但是在出现问题的情况下,我们还是需要考虑做一些调整的。

首先我们来看两个参数的含义:

vm.dirty_ratio:内存中脏数据的限制,内存中的脏数据不能超过这个百分比的值,如果脏数据超出了这个数量。则会直接进行同步刷到磁盘。此时如果有新的I/O请求,将会被阻塞,需要等待脏数据写进磁盘。

dirty_background_ratio:这个参数指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如5%)就会触发pdflush/flush/kdmflush等后台回写进程运行,将一定缓存的脏页异步刷入磁盘中。

当前我们设置的参数:vm.dirty_background_ratio = 5 和vm.dirty_ratio = 80。也就是当达到5%的上限时,后台进程将立即开始异步I/O写入,但是不会强制同步I/O。直到达到80%的满载情况后,系统才会大量的同步写入。当大量同步写入的时候,此时观察到数据库就会出现大量的异常等待。

问题:这里我们考虑一下,如果我们把内存脏数据的限制从80%下调到10%,改成减少缓存的模式会怎么样呢?

修改成减少缓存的模式。将vm.dirty_ratio从80下调到10,这样当开始强制同步I/O的时候,刷脏页是比较少的。虽然会频繁的就触发刷脏页,但是数量下降了,不会一下子刷很多。这样造成的I/O同步的延迟的时间就会变短。关于平衡模式和减少缓存模式的,可以参考Bob Plankers写的文章《Better Linux Disk Caching & Performance with vm.dirty_ratio & vm.dirty_background_ratio》。

同时系统还需要设置min_free_kbytes,这个参数相当重要。当请求分配内存的时候,如果有足够的内存,则可以成功分配,当没有足够内存的时候,操作就会阻塞。他需要等待系统先去释放内存,再分配内存。而对于系统级别的一些原子性的请求,它是不能被阻塞的,如果分配不到内存的话,就会出现失败。内核为了避免原子请求失败,必须设置一块保留的内存。而这个就是通过这个参数来设置的。

vm.min_free_kbytes=10485760

上述参数设置完毕之后,我们还可以补充一个脚本手动来强制刷cache。让cache没达到vm.dirty_background_ratio参数设置的5%就强制刷脏页。

手动刷cache,15分钟1次。

crontab -l
*/15 * * * *  sync && echo 3 > /proc/sys/vm/drop_caches

问题4 Centos 7系统与Oracle软件不兼容问题

做完上述三个调整之后,业务切换到ADG上,白天不会出现问题,但是在半夜仍然会出现问题,同时系统Oracle后台报了大量的trace。如果不清理基本上在一天内能占满300GB。

正常运行的Oracle软件不会出现这么多trace,于是怀疑是Oracle 11gR2软件和Centos 7.5版本存在兼容性问题(主库是Centos 6和Oracle 11g),通过使用另外的一套机器RedHat6搭建了一套新的11g adg环境后,彻底解决了半夜宕机的问题。通过OSWatch可以发现内存的波动是相对稳定的。

结论

其实解决了这么多问题,都只是一些表象,而真正的原因是通过一步一步的踩坑及补锅才能最终发现的。

上述是一个综合性的问题,首先是操作系统和数据库的兼容性有问题,在安装时使用了一些特殊的设置(Centos 7安装Oracle 11g),导致安装后,在高并发业务运行时出现问题,系统产生大量的trace,短时间就能产生几百GB。这些trace文件本身并不会导致问题,只是巧就巧在和系统设置的内存回收机制又有冲突,虽然操作系统一直是达到5%就异步刷新脏页,但是处理能力远远不够。当达到设置的80%时,大量同步刷脏页的时候,系统就会因为I/O请求发生阻塞。因而造成了system cpu变高,然后导致数据库出现各类异常等待事件触发Bug,也会影响监听导致各种连接异常,最终造成数据库宕机影响了业务。

通过改成稳定的操作系统平台Redhat6和数据库11gR2,优化了操作系统内核相关的内存参数,安装了Oracle相关补丁之后,系统再也没出现过类似问题,系统资源使用也相对稳定。

针对这次问题,其实我缺乏的是一种将”线索”串联起来的能力。就单对单线索处理的能力,我们是很强的,但是对于多个“线索”,如何串联起来我们往往有所欠缺。

第一:这个和个人职业经历及遇到的问题、场景是有关系的。如果经历过几次这样的事情,自己的大局观更加开阔,会更早就把问题串联起来进行分析。

第二:这个问题是可以提前预防和发现的,这要求就是多做几轮压力测试,然后再迁移上来。也可以考虑做灰度测试,开启两套程序,一套在生产上运行,一套在ADG上运行。

“庸医”对应的是“神医”,扁鹊在第一次见齐桓公的时候,就说出了:“君有疾在腠理,不治将恐深”。可见扁鹊厉害之处就在于他总能提前发现病情,防患于未然。当“君有疾在骨髓”的时候,扁鹊已经删库跑路了,根本就救不了齐桓公。

我一直认为,会解决问题不牛逼,能把问题扼杀在萌芽才是真正的牛逼,这就要求我们必须锻炼自己的大局观,把系统的整个架构,操作系统、网络、存储、数据库中间层、代理层及程序框架全面打通,就像武侠高手打通任督二脉一样。但这个靠个人学习是很难实现,至少就有100种产品等着我们去研究。

如何做到牛逼不苦逼?其实可以通过一些监控软件来实现大局观,虽然自己有些技术不懂,但通过监控知道哪里出现了问题,就可以联系人来解决。目前我所在公司就有DPM这样的数据库监控软件,有IVORY大数据日志分析平台,这些软件集成在一起就能帮助我迅速找出问题所在,并判断何为对的方向。

作者介绍

袁伟翔,新炬网络高级专家,长期服务于运营商,精通Oracle数据库故障诊断、内核技术,具有10多年数据库开发运维经验。

本文由 dbaplus 社群授权转载。

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/vpktJVQzdorw3fAZGtoB

扫码关注云+社区

领取腾讯云代金券