Used DBMS_STATS.GATHER_TABLE_STATS to gather statistics,but the session hung.

the current db session must be hangs once we run the following command:

exec DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SIEBEL', tabname => 'S_ETL_R_IMG_27', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE, method_opt => 'FOR ALL INDEXED COLUMNS SIZE AUTO',cascade => false, degree => DBMS_STATS.DEFAULT_DEGREE,force=>true);

现像:一运行上面的语句就会hang死,

原由:同事用DAC调用一个job,第一次失败了,紧接着又调了一次,每次job中都有DBMS_STATS.GATHER_TABLE_STATS表分析的语句,到后来,只要一调这个语句就会hang死,只有手工kill session,

分析过程:

个人查看表空间大小,重建了所有索引,都没解决问题,后来只能oracle提SR,帮助分析,

第一个oracle support 分析如下:

You should have two sessions to do as following step by step:

step 1.session 1:
conn / as sysdba
set linesize 300
spool /tmp/session1.txt
select sid from v$mystat where rownum = 1;
SELECT pid,spid,username FROM v$process WHERE addr IN (SELECT paddr FROM v$session WHERE SID IN (Select SID FROM v$mystat WHERE ROWNUM = 1));
alter session set events '10046 trace name context forever, level 12';
exec DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SIEBEL', tabname => 'S_ETL_R_IMG_27', estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE, method_opt => 'FOR ALL INDEXED COLUMNS SIZE AUTO',cascade => false, degree => DBMS_STATS.DEFAULT_DEGREE,force=>true);
if hang,please do step 2

step 2,session 2
conn / as sysdba
spool /tmp/session2.txt
create table current_wait_20130702 as select SYSDATE sdate,a.* from v$session a;
-- wait 10 seconds
insert into current_wait_20130702 as select SYSDATE sdate,a.* from v$session a;
-- wait 10 seconds
insert into current_wait_20130702 as select SYSDATE sdate,a.* from v$session a;
-- wait 20 seconds
insert into current_wait_20130702 as select SYSDATE sdate,a.* from v$session a;
-- wait 20 seconds
insert into current_wait_20130702 as select SYSDATE sdate,a.* from v$session a;
-- wait 30 seconds
insert into current_wait_20130702 as select SYSDATE sdate,a.* from v$session a;

(If there are many processes, the below commands could take more than 10mins.)

SQL>oradebug setmypid
SQL>oradebug unlimit;
SQL>oradebug dump systemstate 266;
Wait for some 30 seconds
SQL>oradebug dump systemstate 266;
SQL>oradebug tracefile_name;==>This will get the system dump trace file name.
spool off;
exit

step 3,session 1:
You can cancel GATHER_TABLE_STATS job. then take following action:
alter session set events '10046 trace name context off';
SELECT blocks,num_rows,last_analyzed FROM Dba_Tables WHERE table_name = 'S_ETL_R_IMG_27';
SELECT owner,segment_name,partition_name,segment_type,tablespace_name,bytes,blocks FROM Dba_Segments WHERE segment_name ='S_ETL_R_IMG_27';
oradebug setmypid;
oradebug tracefile_name;==>This will get the 10046 trace file name.
spool off;


step 4:
1.upload /tmp/session1.txt and /tmp/session2.txt .

2.Please upload alert.log and related trace files.
To find the location for alert log, please connect to database and run following command:
SQL> show parameter background_dump_dest
The alert.log is named as alert_<sid>.log.

3.please upload 10046 trace file.

4.please upload system dump trace file.

5.Please run below commands to list what Oracle patches have been applied:
$cd $ORACLE_HOME/OPatch
$./opatch lsinventory

虽然没找到原因,他的分析方法和思路可以学习一下,

第二个support 给出的思路如下:

1. Are partition tables involved here ?
2. Since when has the problem started ?
3. How long is dbms_stats expected to take ?
4. Does this work fine in any other environment ?
5. Is problem reported for all the tables ?
6. Is there any specific reason we are not on the latest patchset and PSU ? There are many issue which are fixed which you may be hitting otherwise. In a test env can you check if the problem is reported on Latest Patchset and PSU ?

7. Did you already gathered dictionary stats ? Please do :
.SQL> EXECUTE dbms_stats.gather_dictionary_stats;
.SQL> Execute dbms_stats.gather_fixed_objects_stats;
.SQL> EXECUTE dbms_stats.gather_system_stats('start');
. SQL> EXECUTE dbms_stats.gather_system_stats('stop');

8. There are some bugs related to daily automatic statistics history purging may not run, or may only run partially.
And WRI$_OPTSTAT_HISTHEAD_HISTORY could grows continually

We ill need to manually purge old statistics using DBMS_STATS.purge_stats

Please see complete explanation and solution in:
SYSAUX Grows Because Optimizer Stats History is Not Purged (Doc ID 1055547.1)

Please purge stats and try again.
DBMS_STATS.purge_stats

9. Do you have your Tablespace SYSAUX was nearly 100%  ?


最后解决:

因为是生产环境比较紧急,没时间去慢慢试,慢慢研究,最后偿试重启DB,重启完再试这个语句果然就正常执行了,

事后个人分析原因,可能是同事先前第一次执行job失败后,一直占用数据字典里某个资源没释放,然后无论重复做多少次,都会去争这个占用的资源,所以一直会hang住,重启完DB,所有占用的资源都会释放,所以就恢复正常了。

By the way, there is also a workaround for this bug as you can see frommetalink:

So I recommend to try the following command to flush the shared pool,this can be easier than DB restarting and not much impact. In case, thisworkaround does not work well, we can restart the whole database. Just myopinion.

SQL> alter system flush shared_pool;


By the way, there is also a workaround for this bug as you can see frommetalink:

So I recommend to try the following command to flush the shared pool,this can be easier than DB restarting and not much impact. In case, thisworkaround does not work well, we can restart the whole database. Just myopinion.

SQL> alter system flush shared_pool;


最后分析研究这个问题是oracle 的一个BUG,根本解决方案是升级DB版本到11.2.03或以上,

另外还有个workaround 就是刷新一下共享池,

alter system flush shared_pool;


alter system flush shared_pool 将使以前保存的sql执行计划全部清空,
再次执行时这些sql语句时 会产生大量的硬解析,影响数据库的性能

你可能感兴趣的:(Used DBMS_STATS.GATHER_TABLE_STATS to gather statistics,but the session hung.)