适用版本
OceanBase 数据库所有版本。
问题现象
执行 SQL 如下,业务表 set_value 为亿级别数据量。
obclient> select set_id, nvl(applytime,sysdate), nvl(expiretime, to_date('20370101000000','yyyymmddhh24miss')), trim(value) from set_value order by set_id, value, applytime"
查看日志有如下报错信息,并且 OBServer 磁盘使用率达到 100%。
DatabaseException(ORA-00600: internal error code, arguments: -4184, ChunkServer out of disk space) {db_excep_code="602", db_serv_name="bpmdb", db_sql_info="select set_id, nvl(applytime,sysdate), nvl(expiretime, to_date('20370101000000','yyyymmddhh24miss')), trim(value) from set_value order by set_id, value, applytime", db_type="12", db_var_info=""}
问题原因
对临时文件,写入的 buffer 的大小是有上限的,如果写入临时文件的并发度大于 buffer 中可容乃的最大宏块个数,就有可能会产生写入放大问题。可以使用下面的方法确认临时文件宏块是否产生了空间放大。
# 统计临时文件宏块利用率
# total_page_num,总的page数(macro_block_count * 252)
# avg_free_page_nums,每个宏块的平均free page数,
# macro_block_count,总的宏块数
# 4.1及之前版本
grep 'ob_tmp_file*' observer.log.2023031022* | grep 'succeed to wash a block' | grep -o 'free_page_nums:[0-9]*' | awk -F ':' '{ sum += $2; } END { print "total_page_num = " sum; print "avg_free_page_nums = " sum/NR; print "macro_block_count = " NR }'
# 4.2及之后版本
grep 'ob_tmp_file*' observer.log.2023031022* | grep 'succeed to wash a block' | grep -o 'free_page_nums=[0-9]*' | awk -F '=' '{ sum += $2; } END { print "total_page_num = " sum; print "avg_free_page_nums = " sum/NR; print "macro_block_count = " NR }'
解决方法
降低 SQL 执行的并发度,减小对临时文件写入 buffer 的压力,缓解写放大的问题。
增大临时文件写入 buffer 的大小,可以通过调整租户级
_temporary_file_io_area_size配置项(SQL 中间结果(比如:hash join)在存储层能使用的总大小,默认值为 1),降低磁盘排序期间宏块放大问题。obclient> alter system set _temporary_file_io_area_size = '10' tenant = 'xxx';