暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【测试方法】Oracle热块问题的探究

非功能之路 2021-06-10
2234

Oracle热块的问题一直是影响性能瓶颈的重要因素,大部分时候,热块的影响并不大,但是对于某些特性的系统,热块就可能产生很大的影响。

1、热块概述:

当一个会话需要访问一个数据块,而这个数据块正在被另一个用户从磁盘读取到内存中或者这个数据块正在被另一个会话修改时,当前的会话就需要等待,就会产生一个buffer busy waits等待,也伴随着Latch争用。如果太多的会话去访问相同的数据块导致长时间的buffer busy waits等待,通常表现形式为CPU使用率很高,但吞吐量很低,这就是热块。而造成热快的原因可能是数据库设置导致或者重复执行的SQL 频繁访问一些相同的数据块导致。

2、生产上的实例:

客户信息子系统采用了分库分表的方式来处理客户信息过亿的客户数据量,在生产上使用了ADG技术,一套主库一套备库分别处理来自前端的请求。其中主库进行数据的维护操作和查询操作,备库则只进行查询操作。主库在维护后,会实时将数据同步给备库。客户信息的这种模式就给热块创造了有利“繁殖”的温床。

因此,最近在生产上出现了这样一个问题:某交易平均响应时间从200ms变到7s。经分析,是由于该交易为组合交易,包含维护和查询两步操作。而所涉及到的表均为基础信息表,平时读取和DML操作频繁。因此,导致表所在的数据文件IO很高,等待时间长,处理平均时间长。

3、验证热块的实例:

上述例子为生产上的实例,为了更好的理解热块,我们通过以下例子,更好的感知热块:

1)创建表。

CREATE TABLE test2 (ID NUMBER);

2)插入一条记录。

INSERT INTO test2 (ID) VALUES(1);

commit;

3)查看表,看看需要多少一致读。


4)在另一个会话中,做表的更新操作,但并不提交。

BEGIN

 FOR i IN 1..10000 LOOP

    UPDATE test2 SET ID=ID+1;

 END LOOP;

 END;

5)再次查看表,看看需要多少一致读。


        可以明显看到,表同样还是一行记录,第二次查询时耗费的一致读从17增加到19937,原因是oracle的一致读,要求不能读取脏数据块,只能一步一步去寻找数据块的前一个版本

直到找到数据块最初的版本(未更新前的版本),这种通过回滚段寻找数据块前象的过程将耗费大量的IO,更新次数越多,耗费的IO也就越多,这个数据块也就成了著名的热块。

4、如何减少热块的产生:

那么如何减少甚至避免热块的产生呢,首先我们要了解下热块会产生的争用情况,根据不同的争用,有不同的解决方法。常见的Lanch争用分为两种:buffer busy waits 和cache buffer chain。

一、如果是cache buffer chain Latch的,要看访问相同数据块的会话会太长或这个列表太长。

1)如果这个列表太长

原因:

如果一条hash chain比其他hash chain长,它所管理的buffer header更多,那么发生cache buffers chains latch等待的几率就更大,

办法:

针对这个问题,可以通过增加hash bucket的数量进而影响hash chain的数量来达到缩短hash chain的目的参数_db_block_hash_latches。

原理:

Oracle的8.0之前,hash buckets的个数等于db block buffers/4。也就是说,平均一个hash bucket上挂4个block。当然这只是平均值,很有可能通过hash函数转换block header的地址后会导致一个bucket上挂很多个block。

而8.0以后,oracle改成了hash buckets=2*db block buffers。主要是为了降低一个bucket上挂的block的个数,从而减少扫描bucket所花费的时间。所以说,平均是一个bucket上挂0.5个block。但是实际上,一个bucket上可能会挂较多的block,而有些bucket上则没有挂block,这由block的地址决定。所以,增加bucket的个数,就可以增加block平均分布在bucket上的概率。

2)访问相同数据块的会话会太长

原因:

当多个会话重复访问一个或多个由同一个子cache buffer chains锁存器保护的块时,热块就产生。

办法:

调整隐藏参数_spin_count,增加进程成功获取latch的可能性,这个方法要慎用,增大_spin_count会增加cpu的负荷从而可能造成负面效果

二、如果是buffer busy waits

1)找到热块产生的SQL,根据执行计划查看是否合理,改变SQL为最优SQL,例如比如的表的连接方式,访问路径等。

2)加大表或者索引的PCTFREE,使每个数据块中存放更少的行

    调整PCTFREE时,参数虽然是可以动态调整的,但是只能对新的数据插入起作用,对于已经填充过满的老数据块,是无法起作用的,必须调整参数后,对表进行重组,才能对表中的所有数据块都起作用。表中的行分布在更多的数据块上,导致Oracle需要读取更多的数据块来完成查询,大大降低了一个数据块被重复读取的概率。降低了数据的性能。

3)减小表空间BLOCK SIZE,使每个数据块中存放更少的行

如果减小表空间BLOCK SIZE,可能会造成行链接,也可能造成性能上影响。

4)使用hash 簇表和使用HASH 分区表,使数据分布更为分散

5)降低程序的并发度,如果程序中使用了parallel查询,降低parallel degree,以免多个parallel slave同时访问同样的数据对象而形成等待降低性能。

6)把经常操作的小表写入内存。

    通过定位热块导致的争用,我们就能准确快速的找到对应的解决办法,减少热块的产生,提高数据库的性能,保证系统的高效稳定。


文章转载自非功能之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论