oracle统计信息的锁定与解锁

image


(一)问题背景

最近在对一个大约200万行数据的表查看执行计划时,发现存在异常,理论上应该返回100多万笔数据的,但是执行计划只返回了2条数据,比较奇怪,稍微思考,肯定是统计信息出问题了。

explain plan for select * from TABLE_***_NOTIFY where be_id is not null;

clipboard

查看表的统计信息,发现最后一次收集统计信息是在2018年4月22日,已经是2年前的信息了,已经很久没有收集统计信息了

clipboard


(二)Oracle什么情况下会自动收集统计信息

Oracle收集失效的统计信息的策略:自上次自动统计信息收集作业完成之后,如果DBA_TAB_MODIFICATIONS中记录的INSERT+UPDATE+DELETE所影响的行记录之和超过了DBA_TABLES中目标表记录数的10%,或者是自上次统计信息收集完成之后目标表执行过truncate操作,那么Oracle会认为目标表的统计信息已经失效,自动统计信息收集作业就会对目标表重新收集统计信息。


(三)Oracle为什么没有自动收集统计信息

根据上述策略,理论上肯定是要收集统计信息的,那么这里为什么没有收集统计信息呢?

首先想到的是统计信息被关闭了。根据个人经验,在某些公司高并发的业务系统中,统计信息的收集可能会引发异常等待事件,因此会把统计信息关闭,之后要么手动根据DBA_TAB_MODIFICATIONS编写脚本来收集,要么一直不收集,直到执行计划有问题再对单表收集。

那么是不是Oracle的自动统计信息收集功能关闭了呢?查询确认,发现自动统计信息是开启的。

SELECT WINDOW_NAME,AUTOTASK_STATUS,OPTIMIZER_STATS,SEGMENT_ADVISOR,SQL_TUNE_ADVISOR FROM DBA_AUTOTASK_WINDOW_CLIENTS ;

clipboard

既然自动收集统计信息是开启的,那么只有可能是该表的统计信息被锁定了,可以尝试手动收集统计信息

SQL> exec dbms_stats.gather_table_stats(ownname => '***',tabname cascade => true);

发现有如下报错,可以确定是统计信息被锁了,由于过去很久,不知道之前是谁把统计信息给锁了,系统也多次换人接手,已经无从查起。

clipboard


(四)解决办法

既然是统计信息锁了导致无法收集新的统计信息,那么接下来只要解锁并重新收集统计信息即可,方法如下:

--解锁某个表的统计信息 EXEC dbms_stats.unlock_table_stats(ownname '); 重新收集某个表的统计信息 EXEC dbms_stats.gather_table_stats(ownname => true);


还存在一个问题,数据库中可能还存在其他的表也被锁定了统计信息,我如何确认数据库中哪些表的统计信息被锁定:

SELECT owner,table_name,stattype_locked FROM DBA_TAB_STATISTICS a WHERE a.stattype_locked IN (ALLDATACACHE')

备注:stattype_locked为空代表统计信息未锁定。


【完】

相关文章

文章浏览阅读773次,点赞6次,收藏9次。【代码】c# json字符...
文章浏览阅读8.7k次,点赞2次,收藏17次。此现象一般定位到远...
文章浏览阅读2.8k次。mysql脚本转化为oracle脚本_mysql建表语...
文章浏览阅读2.2k次。cx_Oracle报错:cx_Oracle DatabaseErr...
文章浏览阅读1.1k次,点赞38次,收藏35次。本文深入探讨了Or...
文章浏览阅读1.5k次。默认自动收集统计信息的时间为晚上10点...