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

记一次对oracle数据库表空间异常增长的分析和处理

原创 cqiwen 2022-04-22
3455

前言:

前几天,我在对数据库做日常巡检时发现,有一台平时没多少业务量的数据库(通过归档频率、内存占用、会话量等判断),其表空间仍然是以700MB/天的速度在增长,这不合常理。于是我通过以下手段进行了分析,找出了"幕后黑手"。

一、查看表空间增长情况

1.png

二、找出具体在增长的表空间

2.png

三、找出对应表空间中是哪些表导致的空间异常增长

本来想从 dba_hist_seg_stat 视图中去获取有用信息,结果搞了半天发现里面的信息并不全,并且得到的数据也不准确,最终我也没有通过这个视图找到有用的线索。

所谓“条条大路通北京”,上面的路不通,我就换一条稍微绕点的路来获取想要的信息吧。既然已经知道是哪个表空间在异常增长,那么我只需要编写一个存储过程,定时记录这个表空间中所有表的数据变化情况即可。

--先创建用来记录数据的表 create table TB_USAGE_RECORD ( ctime DATE, segment_name VARCHAR2(200), partition_name VARCHAR2(200) segment_type VARCHAR2(30), header_file NUMBER, header_block NUMBER, size_gb NUMBER ) create table TB_USAGE_RECORD_TOTAL ( ctime DATE, total_gb NUMBER ); --创建存储过程(本文中的敏感信息已经进行了改写和处理) create or replace procedure gather_tb_size_increase authid current_user is begin insert into TB_USAGE_RECORD select sysdate ctime,segment_name,partition_name,segment_type,header_file,header_block,round(bytes/1024/1024/1024,3) size_gb from dba_segments where tablespace_name='THE_EXCEPTION_TBS'; insert into TB_USAGE_RECORD_TOTAL select sysdate ctime,round(sum(bytes)/1024/1024/1024,3) total_gb from dba_segments where tablespace_name='THE_EXCEPTION_TBS'; commit; end;

ok,现在我可以马上执行一次存储过程,然后设置一个定时job,让其在明天的这个时候再执行一次。等明天的数据获取到后,即可分析出问题所在!

四、找出问题根源
等第二天的结果出来后,我编写了以下sql并执行,找出数据变化的表:
3.png

查看表中有多少数据:
4.png
发现只有102行数据,查看表结构发现也没有大字段,不应该占用100多M的空间啊!接着分析:

--收集统计信息: analyze table LIST_20220415 compute statistics; --查看实际占用空间大小: select segment_name,partition_name,round(bytes/1024/1024,2) size_mb from dba_segments where segment_name='LIST_20220415' SEGMENT_NAME PARTITION_NAME SIZE_MB 1 LIST_20220415 152 --查看实际占用多少块,是否有空块: select table_name,num_rows,blocks,empty_blocks from dba_tables where table_name='LIST_20220415' TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS 1 LIST_20220415 102 222 19234

实际上数据只使用了222个块,高水位线以下还有19234个空块,所以才导致102行数据占用了(222+19234)*8/1024=152 MB,与dba_segments中查出来的值相同。

所以,应该是业务端向这张表中写入了大量数据,然后又执行了delete操作,删除了大量数据,导致高水位线的产生。

五、问题的处理

根据之前找出的导致数据增长的几张表,我发现它们都是以具体日期命名的。并且我也在数据库的相关存储过程中也找到了创建这几张历史表的sql。至于每天历史表的创建,则是由应用端直接调用存储过程发起。期间应用对历史表执行了一系列操作,从而产生了高水位。为了节约存储空间,一方面是和业务沟通后,要对历史表进行及时地备份和清理,另一方面是要每天对这几张历史表进行高水位线的清理(编写为存储过程,创建job每天定时执行即可)。

以下是清理高水位线后,表的空间占用情况:

SEGMENT_NAME PARTITION_NAME SIZE_MB 1 LIST_20220415 0.31

可见效果还是很显著的,空间占用直接由152MB降低到0.31MB。

经过几天的观察,发现表空间异常增长的现象已经消失:
微信截图_20220424095409.png

(本文完)

最后修改时间:2022-04-24 09:55:26
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论