大家好,這里是公眾號 DBA學(xué)習(xí)之路,分享一些學(xué)習(xí)數(shù)據(jù)庫路上的知識和經(jīng)驗(yàn)。

目錄
- 前言
- 問題描述
- 問題分析
- 問題分析總結(jié)
- 解決方案
- 拓展
- 寫在最后
前言
上周五,開發(fā)同事反饋某套 Oracle 數(shù)據(jù)庫中,大量表的統(tǒng)計(jì)信息已有半年未自動收集,導(dǎo)致執(zhí)行計(jì)劃不準(zhǔn)確,SQL 執(zhí)行頻繁出現(xiàn)問題,每次都需要手動收集統(tǒng)計(jì)信息,希望我能協(xié)助排查并解決這個問題。
本以為是一個常規(guī)問題,但排查過程中發(fā)現(xiàn)了不少問題點(diǎn),最終定位到一個 Oracle 未發(fā)布的 BUG,過程頗為曲折。本文將詳細(xì)分享整個問題的分析思路、排查步驟與解決方案,供大家參考。
問題描述
開始之前,我先說一下環(huán)境信息,這對問題分析比較重要。數(shù)據(jù)庫環(huán)境為 Oracle 19.3 RAC CDB 架構(gòu),有一個從 NON-CDB 遷移而來的 PDB。
據(jù)同事反饋,該庫的自動統(tǒng)計(jì)信息收集任務(wù)已停滯一段時間,檢查其提供的一張表:
SQL> set line2222 pages1000
col TABLE_NAME for a40
col PARTITION_NAME for a30
SELECT TABLE_NAME, PARTITION_NAME, LAST_ANALYZED, NUM_ROWS, BLOCKS
FROM DBA_TAB_STATISTICS
WHERE TABLE_NAME = 'PLC_DC_CDO_NOPDAHIS_ZR';
TABLE_NAME PARTITION_NAME LAST_ANALYZED NUM_ROWS BLOCKS
------------------------------ -------------------- ------------------- ---------- ----------
PLC_DC_CDO_NOPDAHIS_ZR 2025/10/26 11:14:28 302641840 7886515
PLC_DC_CDO_NOPDAHIS_ZR SYS_P54830
PLC_DC_CDO_NOPDAHIS_ZR SYS_P58815
PLC_DC_CDO_NOPDAHIS_ZR SYS_P59994
...(部分分區(qū)信息省略)
PLC_DC_CDO_NOPDAHIS_ZR PART_T01 2025/08/16 10:37:03 0 0
其中 2025/10/26 的統(tǒng)計(jì)信息是手動收集的,上一次自動收集則要追溯到 2025/08/16,確實(shí)已間隔很久。
問題分析
接下來,我根據(jù)我的實(shí)際排查思路進(jìn)行復(fù)盤。
注意:在 CDB 架構(gòu)下,PDB 的統(tǒng)計(jì)信息收集任務(wù)是獨(dú)立的,因此所有檢查都需在 PDB 下進(jìn)行。
檢查任務(wù)狀態(tài)
首先確認(rèn)自動統(tǒng)計(jì)信息收集功能是否開啟:
SQL> SELECT CLIENT_NAME, STATUS
FROM DBA_AUTOTASK_CLIENT
WHERE CLIENT_NAME = 'auto optimizer stats collection';
CLIENT_NAME STATUS
---------------------------------------------------------------- --------
auto optimizer stats collection ENABLED
任務(wù)狀態(tài)顯示為啟用,正常。
檢查任務(wù)窗口
查看統(tǒng)計(jì)信息收集任務(wù)對應(yīng)的調(diào)度窗口組:
SQL> SELECT
CLIENT_NAME,
WINDOW_GROUP
FROM DBA_AUTOTASK_CLIENT
WHERE CLIENT_NAME = 'auto optimizer stats collection';
CLIENT_NAME WINDOW_GROUP
---------------------------------------- ------------------------------
auto optimizer stats collection ORA$AT_WGRP_OS
查看 ORA$AT_WGRP_OS 窗口組包含的具體時間窗口:
SQL> select * from dba_scheduler_wingroup_members where window_group_name='ORA$AT_WGRP_OS';
WINDOW_GROUP_NAME WINDOW_NAME
------------------------------ ------------------------------
ORA$AT_WGRP_OS MONDAY_WINDOW
ORA$AT_WGRP_OS TUESDAY_WINDOW
ORA$AT_WGRP_OS WEDNESDAY_WINDOW
ORA$AT_WGRP_OS THURSDAY_WINDOW
ORA$AT_WGRP_OS FRIDAY_WINDOW
ORA$AT_WGRP_OS SATURDAY_WINDOW
ORA$AT_WGRP_OS SUNDAY_WINDOW
窗口配置正常,按天執(zhí)行。
檢查任務(wù)執(zhí)行情況
檢查近 30 天的任務(wù)執(zhí)行歷史:
SQL> SELECT
WINDOW_NAME,
JOB_NAME,
JOB_STATUS,
JOB_START_TIME,
JOB_DURATION,
JOB_INFO
FROM DBA_AUTOTASK_JOB_HISTORY
WHERE CLIENT_NAME = 'auto optimizer stats collection'
AND JOB_START_TIME >= SYSDATE - 30
ORDER BY JOB_START_TIME DESC;
WINDOW_NAME JOB_NAME JOB_STATUS JOB_START_TIME JOB_DURATION JOB_INFO
-------------------- ------------------------------ ---------- ----------------------------------- -------------------- ----------------------------------------------------------------------------------------------------
SUNDAY_WINDOW ORA$AT_OS_OPT_SY_2061 STOPPED 24-NOV-25 12.00.12.228566 AM PRC +000 01:59:48 REASON="Stop job called because associated window was closed"
SUNDAY_WINDOW ORA$AT_OS_OPT_SY_2041 STOPPED 17-NOV-25 12.00.11.518845 AM PRC +000 01:59:49 REASON="Stop job called because associated window was closed"
SUNDAY_WINDOW ORA$AT_OS_OPT_SY_2021 STOPPED 10-NOV-25 12.00.13.109201 AM PRC +000 01:59:47 REASON="Stop job called because associated window was closed"
SUNDAY_WINDOW ORA$AT_OS_OPT_SY_2001 STOPPED 03-NOV-25 12.00.11.134075 AM PRC +000 01:59:49 REASON="Stop job called because associated window was closed"
歷史記錄顯示,僅周日窗口有執(zhí)行記錄,且狀態(tài)為“STOPPED”,其余窗口均無運(yùn)行記錄。這是否意味著其他窗口被禁用了?
檢查啟用的窗口
進(jìn)一步查看已啟用統(tǒng)計(jì)信息收集的窗口詳情:
SQL> SELECT W.WINDOW_NAME,
W.REPEAT_INTERVAL,
W.DURATION,
W.NEXT_START_DATE,
W.LAST_START_DATE,
W.ENABLED
FROM DBA_AUTOTASK_WINDOW_CLIENTS C, DBA_SCHEDULER_WINDOWS W
WHERE C.WINDOW_NAME = W.WINDOW_NAME
AND C.OPTIMIZER_STATS = 'ENABLED';
WINDOW_NAME REPEAT_INTERVAL DURATION NEXT_START_DATE LAST_START_DATE ENABL
-------------------- ---------------------------------------------------------------------- --------------- ------------------------------------ ------------------------------------ -----
MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0;bysecond=0 +000 04:00:00 01-DEC-25 10.00.00.000000 PM PRC 11-AUG-25 10.00.00.022088 PM PST8PDT TRUE
TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0;bysecond=0 +000 04:00:00 02-DEC-25 10.00.00.000000 PM PRC 12-AUG-25 10.00.00.030151 PM PST8PDT TRUE
WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0;bysecond=0 +000 04:00:00 03-DEC-25 10.00.00.000000 PM PRC 13-AUG-25 10.00.00.142106 PM PST8PDT TRUE
THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0;bysecond=0 +000 04:00:00 04-DEC-25 10.00.00.000000 PM PRC 14-AUG-25 10.00.00.102161 PM PST8PDT TRUE
FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0;bysecond=0 +000 04:00:00 28-NOV-25 10.00.00.000000 PM PRC 15-AUG-25 10.00.00.166076 PM PST8PDT TRUE
SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0;bysecond=0 +000 20:00:00 29-NOV-25 06.00.00.000000 AM PRC 09-AUG-25 06.00.00.070181 AM PST8PDT TRUE
SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0;bysecond=0 +000 20:00:00 30-NOV-25 06.00.00.000000 AM PRC 23-NOV-25 11.59.58.070041 PM PRC TRUE
WEEKEND_WINDOW freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0 +002 00:00:00 29-NOV-25 12.00.00.000000 AM PRC 22-NOV-25 05.59.58.174010 AM PRC TRUE
WEEKNIGHT_WINDOW freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; bysecond=0 +000 08:00:00 28-NOV-25 10.00.00.000000 PM PRC 27-NOV-25 10.00.00.111627 PM PRC TRUE
觀察發(fā)現(xiàn),啟用的窗口包含以下幾類:
- 工作日窗口(MONDAY_WINDOW~FRIDAY_WINDOW):22:00 開始,持續(xù) 4 小時。
- 周末窗口(SATURDAY_WINDOW, SUNDAY_WINDOW):06:00 開始,持續(xù) 20 小時。
- WEEKEND_WINDOW:周六 00:00 開始,持續(xù) 48 小時。
- WEEKNIGHT_WINDOW:周一到周五 22:00 開始,持續(xù) 8 小時。
正常情況下,不應(yīng)出現(xiàn) WEEKEND_WINDOW 和 WEEKNIGHT_WINDOW。這兩個是什么窗口?檢查其所屬窗口組:
SQL> select * from dba_scheduler_wingroup_members where WINDOW_NAME in ('WEEKNIGHT_WINDOW','WEEKEND_WINDOW');
no rows selected
它們不屬于任何窗口組。但關(guān)鍵發(fā)現(xiàn)是:WEEKEND_WINDOW 覆蓋了周末窗口,WEEKNIGHT_WINDOW 覆蓋了工作日窗口!
再觀察各窗口的 LAST_START_DATE:
- 周六至周五的窗口(SATURDAY_WINDOW ~ FRIDAY_WINDOW)最后啟動時間均為 2025 年 8 月,且時區(qū)為 PST8PDT。
- 周日窗口(SUNDAY_WINDOW)、WEEKEND_WINDOW、WEEKNIGHT_WINDOW 最后啟動時間較新,且時區(qū)為 PRC。
這意味著自 2025 年 8 月中旬起,只有周日、WEEKEND、WEEKNIGHT 窗口在運(yùn)行,其余窗口均未執(zhí)行。
檢查窗口執(zhí)行歷史
通過窗口歷史驗(yàn)證上述結(jié)論:
SQL> select * from DBA_AUTOTASK_WINDOW_HISTORY order by WINDOW_START_TIME desc;
WINDOW_NAME WINDOW_START_TIME WINDOW_END_TIME
-------------------- ---------------------------------------- -------------------------------------
WEEKNIGHT_WINDOW 27-NOV-25 10.00.00.462315 PM +08:00 28-NOV-25 06.00.00.059050 AM +08:00
WEEKNIGHT_WINDOW 26-NOV-25 10.00.00.175039 PM +08:00 27-NOV-25 06.00.00.093159 AM +08:00
WEEKNIGHT_WINDOW 25-NOV-25 10.00.00.182260 PM +08:00 26-NOV-25 06.00.00.123977 AM +08:00
WEEKNIGHT_WINDOW 24-NOV-25 10.00.00.248089 PM +08:00 25-NOV-25 06.00.00.083077 AM +08:00
SUNDAY_WINDOW 23-NOV-25 11.59.58.152753 PM +08:00 24-NOV-25 02.00.00.266551 AM +08:00
WEEKEND_WINDOW 22-NOV-25 05.59.58.207990 AM +08:00 23-NOV-25 11.59.58.084099 PM +08:00
WEEKNIGHT_WINDOW 21-NOV-25 10.00.00.268361 PM +08:00 22-NOV-25 05.59.58.179604 AM +08:00
WEEKNIGHT_WINDOW 20-NOV-25 10.00.00.196818 PM +08:00 21-NOV-25 06.00.00.042041 AM +08:00
WEEKNIGHT_WINDOW 19-NOV-25 10.00.00.279480 PM +08:00 20-NOV-25 06.00.00.202939 AM +08:00
WEEKNIGHT_WINDOW 18-NOV-25 10.00.00.226061 PM +08:00 19-NOV-25 06.00.00.095200 AM +08:00
WEEKNIGHT_WINDOW 17-NOV-25 10.00.00.208560 PM +08:00 18-NOV-25 06.00.00.097892 AM +08:00
歷史記錄證實(shí),只有 SUNDAY_WINDOW、WEEKEND_WINDOW 和 WEEKNIGHT_WINDOW 在正常運(yùn)行。WEEKEND 和 WEEKNIGHT 窗口的啟用,導(dǎo)致原有的工作日和周末窗口被覆蓋而無法執(zhí)行。
WEEKEND 和 WEEKNIGHT 窗口分析
通過查閱 MOS 文檔 IF:11g Autotask Jobs Are Not Running as Scheduled. (Doc ID 2084941.1) 得知:
WEEKNIGHT_WINDOW和WEEKEND_WINDOW是 Oracle 10g 時期使用的調(diào)度窗口,高版本雖保留但不建議使用。

檢查當(dāng)前 PDB 中這兩個窗口的狀態(tài):
SQL> select window_name, enabled from dba_scheduler_windows where window_name in ('WEEKNIGHT_WINDOW','WEEKEND_WINDOW');
WINDOW_NAME ENABLED
------------------------------ ----------
WEEKNIGHT_WINDOW TRUE
WEEKEND_WINDOW TRUE
查詢顯示為 TRUE,這就是為什么統(tǒng)計(jì)信息收集任務(wù)的窗口沒有正常執(zhí)行的根本原因。
解決方法很簡單,直接禁用這兩個窗口:
SQL> exec dbms_scheduler.disable('WEEKNIGHT_WINDOW'); exec dbms_scheduler.disable('WEEKEND_WINDOW');
周五禁用后,周一檢查窗口狀態(tài),周五、周六、周日的窗口已恢復(fù)正常執(zhí)行:
WINDOW_NAME REPEAT_INTERVAL DURATION NEXT_START_DATE LAST_START_DATE ENABL
-------------------- ------------------------------------------------------------ -------------------- ----------------------------------- ------------------------------------ -----
MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0;bysecond=0 +000 04:00:00 01-DEC-25 10.00.00.000000 PM PRC 11-AUG-25 10.00.00.022088 PM PST8PDT TRUE
TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0;bysecond=0 +000 04:00:00 02-DEC-25 10.00.00.000000 PM PRC 12-AUG-25 10.00.00.030151 PM PST8PDT TRUE
WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0;bysecond=0 +000 04:00:00 03-DEC-25 10.00.00.000000 PM PRC 13-AUG-25 10.00.00.142106 PM PST8PDT TRUE
THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0;bysecond=0 +000 04:00:00 04-DEC-25 10.00.00.000000 PM PRC 14-AUG-25 10.00.00.102161 PM PST8PDT TRUE
FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0;bysecond=0 +000 04:00:00 05-DEC-25 10.00.00.000000 PM PRC 28-NOV-25 10.00.00.021661 PM PRC TRUE
SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0;bysecond=0 +000 20:00:00 06-DEC-25 06.00.00.000000 AM PRC 29-NOV-25 06.00.00.069636 AM PRC TRUE
SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0;bysecond=0 +000 20:00:00 07-DEC-25 06.00.00.000000 AM PRC 30-NOV-25 06.00.00.087849 AM PRC TRUE
時區(qū)問題分析
窗口執(zhí)行的問題已經(jīng)解決了,但是時區(qū)的問題還是比較困惑,所以繼續(xù)分析了一下時區(qū)的問題。
MOS 文檔參考
關(guān)于時區(qū)問題,我查閱 MOS 之后發(fā)現(xiàn)了一個相關(guān)的文檔:Default Scheduler Timezone Value In PDB$SEED Different Than CDB (Doc ID 2702230.1)
文檔中提到:

結(jié)論:使用 DBCA General 模式創(chuàng)建的 CDB 數(shù)據(jù)庫,其 PDB$SEED 的默認(rèn) Scheduler 時區(qū)獨(dú)立于 CDB$ROOT,具體規(guī)則為:
- 12C & 18C:
Etc/UTC - 19C:
PST8PDT
若使用 CREATE DATABASE 命令或 DBCA 自定義(customize) 模式創(chuàng)建,則無此問題,PDB$SEED 會繼承 CDB$ROOT 的 Scheduler 時區(qū)。
環(huán)境時區(qū)檢查
檢查當(dāng)前環(huán)境的時區(qū)設(shè)置:
-- CDB$ROOT 時區(qū)
SQL> select * from cdb_scheduler_global_attribute where ATTRIBUTE_NAME like '%TIMEZONE%';
ATTRIBUTE_NAME VALUE
------------------------------ ----------
DEFAULT_TIMEZONE PRC
-- PDB$SEED 時區(qū)
SQL> alter session set container=PDB$SEED;
SQL> select * from dba_scheduler_global_attribute where ATTRIBUTE_NAME like '%TIMEZONE%';
ATTRIBUTE_NAME VALUE
------------------------------ ------------------------------
DEFAULT_TIMEZONE PST8PDT
-- 用戶 PDB 時區(qū)
SQL> alter session set container=RPTDB;
SQL> select * from dba_scheduler_global_attribute where ATTRIBUTE_NAME like '%TIMEZONE%';
ATTRIBUTE_NAME VALUE
------------------------------ ----------
DEFAULT_TIMEZONE PRC
可以發(fā)現(xiàn),PDB$SEED 的 Scheduler 時區(qū)為 PST8PDT(符合上述 BUG 描述),用戶 PDB 的 Scheduler 時區(qū)為 PRC(推測為人為修改過)。
實(shí)戰(zhàn)驗(yàn)證
通過創(chuàng)建測試 PDB 驗(yàn)證時區(qū)繼承行為:
-- 從 PDB$SEED 創(chuàng)建一個測試 PDB
SQL> create pluggable database test admin user admin identified by oracle;
SQL> alter pluggable database test open;
SQL> alter session set container=TEST;
-- 檢查新建 PDB 的 scheduler 時區(qū)
SQL> select * from dba_scheduler_global_attribute where ATTRIBUTE_NAME like '%TIMEZONE%';
ATTRIBUTE_NAME VALUE
------------------------------ ----------
DEFAULT_TIMEZONE PST8PDT
結(jié)論:在不人為干預(yù)的情況下,新建 PDB 會從 PDB$SEED 繼承 PST8PDT 時區(qū)。
查看自動任務(wù)優(yōu)化器統(tǒng)計(jì)信息收集所使用的窗口時間:
SQL> SELECT W.WINDOW_NAME,
W.REPEAT_INTERVAL,
W.DURATION,
W.NEXT_START_DATE,
W.LAST_START_DATE,
W.ENABLED
FROM DBA_AUTOTASK_WINDOW_CLIENTS C, DBA_SCHEDULER_WINDOWS W
WHERE C.WINDOW_NAME = W.WINDOW_NAME
AND C.OPTIMIZER_STATS = 'ENABLED';
WINDOW_NAME
REPEAT_INTERVAL DURATION NEXT_START_DATE LAST_START_DATE ENABL
-------------------- ---------------------------------------------------------------------- --------------- ------------------------------------ ------------------------- -----
SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0 +000 20:00:00 06-DEC-25 06.00.00.000000 AM PST8PDT TRUE
MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0 +000 04:00:00 01-DEC-25 10.00.00.000000 PM PST8PDT TRUE
FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0 +000 04:00:00 05-DEC-25 10.00.00.000000 PM PST8PDT TRUE
WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0 +000 04:00:00 03-DEC-25 10.00.00.000000 PM PST8PDT TRUE
TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0 +000 04:00:00 02-DEC-25 10.00.00.000000 PM PST8PDT TRUE
SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 07-DEC-25 06.00.00.000000 AM PST8PDT TRUE
THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0 +000 04:00:00 04-DEC-25 10.00.00.000000 PM PST8PDT TRUE
可以發(fā)現(xiàn),NEXT_START_DATE 字段顯示的是 PST8PDT,也就是說從 PDB$SEED 繼承過來的默認(rèn)時區(qū)是 PST8PDT(太平洋時間)。此時,如果默認(rèn)不修改時區(qū),自動任務(wù)優(yōu)化器統(tǒng)計(jì)信息收集會在太平洋時間的晚上 10 點(diǎn)和早上 6 點(diǎn)運(yùn)行,這顯然是錯誤的。
修復(fù)這個問題,可手動修改 PDB 的 scheduler 時區(qū):
-- 切換到 TEST PDB
SQL> alter session set container=TEST;
Session altered.
-- 調(diào)整 TEST PDB 的 scheduler 時區(qū)為 PRC
SQL> EXEC DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('default_timezone', 'PRC');
PL/SQL procedure successfully completed.
-- 修改后檢查 TEST PDB 的 scheduler 時區(qū)
SQL> select * from dba_scheduler_global_attribute where ATTRIBUTE_NAME like '%TIMEZONE%';
ATTRIBUTE_NAME VALUE
------------------------------ ----------
DEFAULT_TIMEZONE PRC
修改后,自動任務(wù)窗口的 NEXT_START_DATE 將更新為 PRC 時區(qū)下的正確時間。
再次檢查自動任務(wù)優(yōu)化器統(tǒng)計(jì)信息收集所使用的窗口時間:
SQL> SELECT W.WINDOW_NAME,
W.REPEAT_INTERVAL,
W.DURATION,
W.NEXT_START_DATE,
W.LAST_START_DATE,
W.ENABLED
FROM DBA_AUTOTASK_WINDOW_CLIENTS C, DBA_SCHEDULER_WINDOWS W
WHERE C.WINDOW_NAME = W.WINDOW_NAME
AND C.OPTIMIZER_STATS = 'ENABLED';
WINDOW_NAME REPEAT_INTERVAL DURATION NEXT_START_DATE LAST_START_DATE ENABL
-------------------- ---------------------------------------------------------------------- --------------- ------------------------------------ ------------------------- -----
SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0 +000 20:00:00 06-DEC-25 06.00.00.000000 AM PRC TRUE
MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0 +000 04:00:00 08-DEC-25 10.00.00.000000 PM PRC TRUE
FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0 +000 04:00:00 05-DEC-25 10.00.00.000000 PM PRC TRUE
WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0 +000 04:00:00 03-DEC-25 10.00.00.000000 PM PRC TRUE
TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0 +000 04:00:00 02-DEC-25 10.00.00.000000 PM PRC TRUE
SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 07-DEC-25 06.00.00.000000 AM PRC TRUE
THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0 +000 04:00:00 04-DEC-25 10.00.00.000000 PM PRC TRUE
修改完之后,LAST_START_DATE 字段顯示已經(jīng)修改為 PRC 了。
問題分析總結(jié)
基于以上排查,可以還原大致的問題時間線:
- 目標(biāo) CDB 庫通過
DBCA General模式創(chuàng)建,導(dǎo)致PDB$SEED的 Scheduler 時區(qū)默認(rèn)為PST8PDT。 - 原 NON-CDB 庫通過
DBMS_PDB.DESCRIBE方式遷移,作為 PDB 插入該 CDB。此過程會基于PDB$SEED創(chuàng)建 PDB 的元數(shù)據(jù),因此繼承了PST8PDT時區(qū)。 - 遷移完成后,PDB 運(yùn)行一段時間,DBA 發(fā)現(xiàn)統(tǒng)計(jì)信息收集任務(wù)執(zhí)行時間(顯示為太平洋時間)與實(shí)際不符。
- 可能為了解決時間問題,啟用了
WEEKEND_WINDOW和WEEKNIGHT_WINDOW這兩個窗口。 - DBA 后面發(fā)現(xiàn)了時區(qū)問題,手動將 PDB 的 Scheduler 時區(qū)修改為
PRC。 - 但未禁用
WEEKEND_WINDOW和WEEKNIGHT_WINDOW窗口,導(dǎo)致這兩個窗口覆蓋了原有的周一至周六窗口,致使統(tǒng)計(jì)信息收集任務(wù)長期無法在正確時間觸發(fā)。
解決方案
目前這個時區(qū) BUG 尚未被 Oracle 正式發(fā)布修復(fù)。建議針對所有使用 CDB 架構(gòu)的數(shù)據(jù)庫進(jìn)行檢查:
SQL> alter session set container=MES;
Session altered.
SQL> select * from dba_scheduler_global_attribute where ATTRIBUTE_NAME like '%TIMEZONE%';
ATTRIBUTE_NAME VALUE
-------------------- ----------
DEFAULT_TIMEZONE PST8PDT
SQL> SELECT W.WINDOW_NAME,
W.REPEAT_INTERVAL,
W.DURATION,
W.NEXT_START_DATE,
W.LAST_START_DATE,
W.ENABLED
FROM DBA_AUTOTASK_WINDOW_CLIENTS C, DBA_SCHEDULER_WINDOWS W
WHERE C.WINDOW_NAME = W.WINDOW_NAME
AND C.OPTIMIZER_STATS = 'ENABLED';
WINDOW_NAME REPEAT_INTERVAL DURATION NEXT_START_DATE LAST_START_DATE ENABL
-------------------- ------------------------------------------------------------ --------------- ------------------------------------ ------------------------------------ -----
MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0 +000 04:00:00 01-DEC-25 10.00.00.000000 PM PST8PDT 24-NOV-25 10.00.00.110249 PM PST8PDT TRUE
TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0 +000 04:00:00 02-DEC-25 10.00.00.000000 PM PST8PDT 25-NOV-25 10.00.00.166222 PM PST8PDT TRUE
WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0 +000 04:00:00 03-DEC-25 10.00.00.000000 PM PST8PDT 26-NOV-25 10.00.00.158350 PM PST8PDT TRUE
THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0 +000 04:00:00 04-DEC-25 10.00.00.000000 PM PST8PDT 27-NOV-25 10.00.00.022223 PM PST8PDT TRUE
FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0 +000 04:00:00 05-DEC-25 10.00.00.000000 PM PST8PDT 28-NOV-25 10.00.00.030350 PM PST8PDT TRUE
SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0 +000 20:00:00 06-DEC-25 06.00.00.000000 AM PST8PDT 29-NOV-25 06.00.00.126232 AM PST8PDT TRUE
SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 07-DEC-25 06.00.00.000000 AM PST8PDT 30-NOV-25 06.00.00.206237 AM PST8PDT TRUE
這個問題的解決方案,上面分析過程中其實(shí)已經(jīng)提供了:
-- 禁用 10g 版本的 WEEKEND 和 WEEKNIGHT 窗口
SQL> exec dbms_scheduler.disable('WEEKNIGHT_WINDOW');
exec dbms_scheduler.disable('WEEKEND_WINDOW');
-- 修改 PDB 時區(qū)為 PRC
SQL> EXEC DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('default_timezone', 'PRC');
PL/SQL procedure successfully completed.
執(zhí)行完之后,窗口的 NEXT_START_DATE 已經(jīng)更新為正確的了:
WINDOW_NAME REPEAT_INTERVAL DURATION NEXT_START_DATE LAST_START_DATE ENABL
-------------------- ------------------------------------------------------------ --------------- ------------------------------------ ------------------------------------ -----
MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0 +000 04:00:00 08-DEC-25 10.00.00.000000 PM PRC 24-NOV-25 10.00.00.110249 PM PST8PDT TRUE
TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0 +000 04:00:00 02-DEC-25 10.00.00.000000 PM PRC 25-NOV-25 10.00.00.166222 PM PST8PDT TRUE
WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0 +000 04:00:00 03-DEC-25 10.00.00.000000 PM PRC 26-NOV-25 10.00.00.158350 PM PST8PDT TRUE
THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0 +000 04:00:00 04-DEC-25 10.00.00.000000 PM PRC 27-NOV-25 10.00.00.022223 PM PST8PDT TRUE
FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0 +000 04:00:00 05-DEC-25 10.00.00.000000 PM PRC 28-NOV-25 10.00.00.030350 PM PST8PDT TRUE
SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0 +000 20:00:00 06-DEC-25 06.00.00.000000 AM PRC 29-NOV-25 06.00.00.126232 AM PST8PDT TRUE
SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 07-DEC-25 06.00.00.000000 AM PRC 30-NOV-25 06.00.00.206237 AM PST8PDT TRUE
執(zhí)行后,各窗口的 NEXT_START_DATE 將更新為 PRC 時區(qū)下的正確時間,LAST_START_DATE 將在下次窗口執(zhí)行后同步更新。
拓展
統(tǒng)計(jì)信息收集任務(wù)雖然已經(jīng)解決,但是由于接近半年沒有收集統(tǒng)計(jì)信息,所以很多表收集會耗費(fèi)很多時間,導(dǎo)致每天收集都會無法執(zhí)行完成。
為了解決這個問題,可以將收集任務(wù)中時間大于 30 分鐘的大表進(jìn)行手動單獨(dú)收集:
SQL> spool /tmp/dba_autotask_table30min.html
set markup html on
SELECT
target,
start_time,
end_time,
(end_time - start_time) AS elapsed_time, -- interval
(
EXTRACT(DAY FROM (end_time - start_time)) * 1440 +
EXTRACT(HOUR FROM (end_time - start_time)) * 60 +
EXTRACT(MINUTE FROM (end_time - start_time)) +
EXTRACT(SECOND FROM (end_time - start_time)) / 60
) AS elapsed_minutes,
notes
FROM dba_optstat_operation_tasks
WHERE end_time IS NOT NULL
AND (
EXTRACT(DAY FROM (end_time - start_time)) * 1440 +
EXTRACT(HOUR FROM (end_time - start_time)) * 60 +
EXTRACT(MINUTE FROM (end_time - start_time)) +
EXTRACT(SECOND FROM (end_time - start_time)) / 60
) > 30
ORDER BY start_time DESC;
spool off
set markup html off
使用以上命令可以獲取統(tǒng)計(jì)信息運(yùn)行超過 30 分鐘的表,然后通過以下命令手動收集這些表:
SQL> exec dbms_stats.lock_table_stats('<OWNER>', '<TABLE_NAME>'); SQL> exec dbms_stats.gather_table_stats(ownname=>'<OWNER>',tabname =>'<TABLE_NAME>',estimate_percent =>DBMS_STATS.AUTO_SAMPLE_SIZE,method_opt => 'FOR ALL COLUMNS SIZE AUTO',cascade=>true, DEGREE=> DBMS_STATS.AUTO_DEGREE);
建議您可以先鎖住它們,然后手動收集輸出里每個表的統(tǒng)計(jì)信息。
寫在最后
這個 BUG 表面上看只是時區(qū)顯示問題,似乎不影響統(tǒng)計(jì)信息收集任務(wù)本身。但深入思考,統(tǒng)計(jì)信息收集任務(wù)通常被安排在業(yè)務(wù)低峰期(如夜間)執(zhí)行,以避免對生產(chǎn)系統(tǒng)造成性能沖擊。如果因時區(qū)錯誤導(dǎo)致任務(wù)實(shí)際在業(yè)務(wù)高峰期執(zhí)行,極易引發(fā)嚴(yán)重的性能問題,影響生產(chǎn)環(huán)境的穩(wěn)定運(yùn)行。
因此,建議所有 Oracle CDB 用戶檢查 PDB 的 Scheduler 時區(qū)設(shè)置,防患于未然。





