SMON功能-SMON_SCN_TIME字典基表

SMON後臺進程的作用還包括維護SMON_SCN_TIME基表。

SMON_SCN_TIME基表用於記錄過去時間段中SCN(system change number)與具體的時間戳(timestamp)之間的映射關係,因爲是採樣記錄這種映射關係,所以SMON_SCN_TIME可以較爲較爲粗糙地(不精確地)定位某個SCN的時間信息。實際的SMON_SCN_TIME是一張cluster table簇表。

 

 

 

SMON_SCN_TIME時間映射表最大的用途是爲閃回類型的查詢(flashback type queries)提供一種將時間映射爲SCN的途徑(The SMON time mapping is mainly for flashback type queries to map a time to an SCN)。

 

Metalink文檔<Error ORA-01466 while executing a flashback query. [ID 281510.1]>介紹了SMON更新SMON_SCN_TIME的規律:

  • 在版本10g中SMON_SCN_TIME每6秒鐘被更新一次(In Oracle Database 10g, smon_scn_time is updated every 6 seconds hence that is the minimum time that the flashback query time needs to be behind the timestamp of the first change to the table.)
  • 在版本9.2中SMON_SCN_TIME每5分鐘被更新一次(In Oracle Database 9.2, smon_scn_time is updated every 5 minutes hence the required delay between the flashback time and table properties change is at least 5 minutes.)

 

另外從10g開始SMON也會清理SMON_SCN_TIME中的記錄了,SMON後臺進程會每5分鐘被喚醒一次,檢查SMON_SCN_TIME在磁盤上的映射記錄總數,若總數超過144000條,則會使用以下語句刪除最老的一條記錄(time_mp最小):

 

delete from smon_scn_time
 where thread = 0
   and time_mp = (select min(time_mp) from smon_scn_time where thread = 0)

 

若僅僅刪除一條記錄不足以獲得足夠的空間,那麼SMON會反覆多次執行以上DELETE語句。

 

觸發場景

 

雖然Metalink文檔<Error ORA-01466 while executing a flashback query. [ID 281510.1]>指出了在10g中SMON會以每6秒一次的頻率更新SMON_SCN_TIME基表,但是實際觀測可以發現更新頻率與SCN的增長速率相關,在較爲繁忙的實例中SCN的上升極快時SMON可能會以6秒一次的最短間隔頻率更新 , 但是在空閒的實例中SCN增長較慢,則仍會以每5或10分鐘一次頻率更新,例如:

 

[oracle@vrh8 ~]$ ps -ef|grep smon|grep -v grep
oracle    3484     1  0 Nov12 ?        00:00:02 ora_smon_G10R21

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production

SQL> select * from global_name;

GLOBAL_NAME
--------------------------------------------------------------------------------
www.askmaclean.com & www.askmaclean.com

SQL> oradebug setospid 3484;
Oracle pid: 8, Unix process pid: 3484, image: [email protected] (SMON)

SQL> oradebug event 10500 trace name context forever,level 10 : 10046 trace name context forever,level 12;
Statement processed.
SQL>
SQL> oradebug tracefile_name;
/s01/admin/G10R21/bdump/g10r21_smon_3484.trc

/* 等待一定時間 */

 

找出SMON trace文件中insert數據到SMON_SCN_TIME的記錄:

 

 grep -A20 "insert into smon_scn_time" /s01/admin/G10R21/bdump/g10r21_smon_3484.trc

insert into smon_scn_time (thread, time_mp, time_dp, scn, scn_wrp, scn_bas,  num_mappings, tim_scn_map)
values (0, :1, :2, :3, :4, :5, :6, :7)
END OF STMT
PARSE #4:c=0,e=43,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1290280848899596
BINDS #4:
kkscoacd
 Bind#0
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fb29844edb8  bln=22  avl=06  flg=05
  value=767145793
 Bind#1
  oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=8 off=0
  kxsbbbfp=7fff023ae780  bln=07  avl=07  flg=09
  value="11/14/2011 0:3:13"
 Bind#2
  oacdty=02 mxl=22(04) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fff023ae70c  bln=22  avl=04  flg=09
  value=954389
 Bind#3
--
insert into smon_scn_time (thread, time_mp, time_dp, scn, scn_wrp, scn_bas,  num_mappings, tim_scn_map)
values (0, :1, :2, :3, :4, :5, :6, :7)
END OF STMT
PARSE #1:c=0,e=21,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1290281434933390
BINDS #1:
kkscoacd
 Bind#0
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fb29844edb8  bln=22  avl=06  flg=05
  value=767146393
 Bind#1
  oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=8 off=0
  kxsbbbfp=7fff023ae780  bln=07  avl=07  flg=09
  value="11/14/2011 0:13:13"
 Bind#2
  oacdty=02 mxl=22(04) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fff023ae70c  bln=22  avl=04  flg=09
  value=954720
 Bind#3
--
insert into smon_scn_time (thread, time_mp, time_dp, scn, scn_wrp, scn_bas,  num_mappings, tim_scn_map)
values (0, :1, :2, :3, :4, :5, :6, :7)
END OF STMT
PARSE #3:c=0,e=20,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1290281727955249
BINDS #3:
kkscoacd
 Bind#0
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fb29844e960  bln=22  avl=06  flg=05
  value=767146993
 Bind#1
  oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=8 off=0
  kxsbbbfp=7fff023ae780  bln=07  avl=07  flg=09
  value="11/14/2011 0:23:13"
 Bind#2
  oacdty=02 mxl=22(04) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fff023ae70c  bln=22  avl=04  flg=09
  value=954926
 Bind#3
insert into smon_scn_time (thread, time_mp, time_dp, scn, scn_wrp, scn_bas,  num_mappings, tim_scn_map)
values (0, :1, :2, :3, :4, :5, :6, :7)
END OF STMT
PARSE #4:c=0,e=30,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=1290282313990553
BINDS #4:
kkscoacd
 Bind#0
  oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
  oacflg=00 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fb29844edb8  bln=22  avl=06  flg=05
  value=767147294
 Bind#1
  oacdty=12 mxl=07(07) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=8 off=0
  kxsbbbfp=7fff023ae780  bln=07  avl=07  flg=09
  value="11/14/2011 0:28:14"
 Bind#2
  oacdty=02 mxl=22(04) mxlc=00 mal=00 scl=00 pre=00
  oacflg=10 fl2=0001 frm=00 csi=00 siz=24 off=0
  kxsbbbfp=7fff023ae70c  bln=22  avl=04  flg=09
  value=955036
 Bind#3

 

 

可以通過以上INSERT語句的TIME_DP綁定變量值中發現其更新SMON_SCN_TIME的時間規律,一般爲5或10分鐘一次。這說明SMON_SCN_TIME的更細頻率與數據庫實例的負載有關,其最短的間隔是每6秒一次,最長的間隔爲10分鐘一次。

 

由於SMON_SCN_TIME的更新頻率問題可能引起ORA-01466錯誤,詳見:
Error ORA-01466 while executing a flashback query. [ID 281510.1]

 

由於SMON_SCN_TIME的數據不一致可能引起ORA-00600[6711]或頻繁地執行”delete from smon_scn_time”刪除語句,詳見:
ORA-00600[6711]錯誤一例
High Executions Of Statement “delete from smon_scn_time…” [ID 375401.1]

 

SMON維護SMON_SCN_TIME時相關的Stack CALL,ktf_scn_time是更新SMON_SCN_TIME的主要函數:

 

ksedst ksedmp ssexhd kghlkremf kghalo kghgex kghalf kksLoadChild kxsGetRuntimeLock kksfbc
kkspsc0 kksParseCursor opiosq0 opiall0 opikpr opiodr rpidrus skgmstack rpidru rpiswu2 kprball
ktf_scn_time
ktmmon ktmSmonMain ksbrdp opirip opidrv sou2o opimai_real main main_opd_entry

 

SMON 還可能使用以下SQL語句維護SMON_SCN_TIME字典基表:

 

select smontabv.cnt,
       smontab.time_mp,
       smontab.scn,
       smontab.num_mappings,
       smontab.tim_scn_map,
       smontab.orig_thread
  from smon_scn_time smontab,
       (select max(scn) scnmax,
               count(*) + sum(NVL2(TIM_SCN_MAP, NUM_MAPPINGS, 0)) cnt
          from smon_scn_time
         where thread = 0) smontabv
 where smontab.scn = smontabv.scnmax
   and thread = 0

insert into smon_scn_time
  (thread,
   time_mp,
   time_dp,
   scn,
   scn_wrp,
   scn_bas,
   num_mappings,
   tim_scn_map)
values
  (0, :1, :2, :3, :4, :5, :6, :7)

update smon_scn_time
   set orig_thread  = 0,
       time_mp      = :1,
       time_dp      = :2,
       scn          = :3,
       scn_wrp      = :4,
       scn_bas      = :5,
       num_mappings = :6,
       tim_scn_map  = :7
 where thread = 0
   and scn = (select min(scn) from smon_scn_time where thread = 0)

delete from smon_scn_time
 where thread = 0
   and scn = (select min(scn) from smon_scn_time where thread = 0)

 

如何禁止SMON更新SMON_SCN_TIME基表

 

 

可以通過設置診斷事件event=’12500 trace name context forever, level 10’來禁止SMON更新SMON_SCN_TIME基表(Setting the 12500 event at system level should stop SMON from updating the SMON_SCN_TIME table.):

SQL>  alter system set events '12500 trace name context forever, level 10';

System altered.

 

一般我們不推薦禁止SMON更新SMON_SCN_TIME基表,因爲這樣會影響flashback Query閃回查詢的正常使用,但是在某些異常恢復的場景中SMON_SCN_TIME數據訛誤可能導致實例的Crash,那麼可以利用以上12500事件做到不觸發SMON_SCN_TIME被更新。

 

 

如何手動清除SMON_SCN_TIME的數據

 

因爲SMON_SCN_TIME不是bootstrap自舉核心對象,所以我們可以手動更新該表上的數據、及重建其索引。

如我在<ORA-00600[6711]錯誤一例>中介紹了因爲SMON_SCN_TIME與其索引的數據不一致時,可以通過重建索引來解決問題:

connect / as sysdba
drop index smon_scn_time_scn_idx;
drop index smon_scn_time_tim_idx;
create unique index smon_scn_time_scn_idx on smon_scn_time(scn);
create unique index smon_scn_time_tim_idx on smon_scn_time(time_mp);
analyze table smon_scn_time validate structure cascade;

 

可以在設置了12500事件後手動刪除SMON_SCN_TIME上的記錄,重啓實例後SMON會繼續正常更新SMON_SCN_TIME。除非是因爲SMON_SCN_TIME表上的記錄與索引smon_scn_time_tim_idx或smon_scn_time_scn_idx上的不一致造成DELETE語句無法有效刪除該表上的記錄:文檔<LOCK ON SYS.SMON_SCN_TIME [ID 747745.1]>說明了該問題,否則我們沒有必要手動去清除SMON_SCN_TIME上的數據。

具體方法如下:

 

SQL> conn / as sysdba

/* Set the event at system level */

SQL> alter system set events '12500 trace name context forever, level 10';

/* Delete the records from SMON_SCN_TIME */

SQL> delete from smon_scn_time;

SQL> commit;

SQL> alter system set events '12500 trace name context off';

完成以上步驟後重啓實例restart instance

shutdown immediate;
startup;

SMON_SCN_TIME表存放的是SCN和Time之前的映射關係。 該表由SMON 進程負責維護。

 

SQL> desc smon_scn_time

 Name                                     Null?    Type

 ------------------------------------------------- ----------------------------

 THREAD                                            NUMBER

 TIME_MP                                            NUMBER

 TIME_DP                                           DATE

 SCN_WRP                                           NUMBER

 SCN_BAS                                           NUMBER

 NUM_MAPPINGS                                       NUMBER

 TIM_SCN_MAP                                       RAW(1200)

 SCN                                               NUMBER

 ORIG_THREAD                                        NUMBER

 

SQL> alter session set nls_date_format='yyyy-mm-ddhh24:mi:ss';

Session altered.

 

SQL> select time_dp,scn from smon_scn_time where rownum<5;

TIME_DP                    SCN

------------------- ----------

2013-03-15 10:31:04    2092348

2013-03-15 10:35:49    2092452

2013-03-15 10:41:00    2092581

2013-03-15 10:45:46    2092682

 

 

在Oracle 11g中,該表的創建SQL在$ORACLE_HOME/rdbms/admin/dtxnspc.bsq 文件中。

 

create table smon_scn_time (

 thread number,                        /* thread, compatibility */

 time_mp number,                       /* time this recent scn represents */

 time_dp date,                         /* time as date, compatibility */

  scn_wrpnumber,                        /*scn.wrp, compatibility */

 scn_bas number,                       /* scn.bas, compatibility */

 num_mappings number,

 tim_scn_map raw(1200),

  scnnumber default 0,                  /* scn*/

 orig_thread number default 0          /* for downgrade */

) cluster smon_scn_to_time_aux (thread)

/

create unique index smon_scn_time_tim_idxon smon_scn_time(time_mp)

 tablespace SYSAUX

/

create unique index smon_scn_time_scn_idxon smon_scn_time(scn)

 tablespace SYSAUX

/

 

我們可以直接delete掉SMON_SCN_TIME表中的記錄:

SQL> delete from smon_scn_time;

2120 rows deleted.

 

SQL> commit;

Commit complete.

 

SQL> select count(1) from smon_scn_time;

 COUNT(1)

----------

        0

 

 

二.SMON_SCN_TIME表記錄保存策略說明

 

2.1 Oracle 9i

 

根據MOS文檔的說明:

How To Map SCN To Timestamp Before 10g? [ID365536.1]

 

SYS.SMON_SCN_TIMEwill have a maximum of 1440 rows and each record will be for a 5 minute period.Oracle maintains this information for a maximum of 5 days after which therecords will be recycled.

 

This means thatdata is stored 12 times per hour * 24 hours * 5 days = 1440 rows.  

 

    在Oracle 9i版本中,SMON_SCN_TIME 表中最多存放1440條記錄。 SMON 進程每隔5分鐘生成一次SCN和TIME 之前的映射,並更新到SMON_SCN_TIME表。該表的維護週期是5天。

    因此該表最多存放的記錄是:12*24*5=1440條記錄。

 

    超過1440條的記錄在下次循環中會被刪除。

 

 

2.2 Oracle 10g以後的版本

    在oracle 10g以後的版本,SMON_SCN_TIME表的維護策略發生了變化。

 

根據MOS文檔的說明:

High Executions Of Statement "deletefrom smon_scn_time..." [ID 375401.1]

 

The deletestatement deletes the oldest rows from smon_scn_time to clear space for newrows.  SMON wakes up every 5 minutes and checks how many on-disk mappingswe have--the max is 144000.

    --SMON進程每個5分鐘喚醒一次來更新SCN和TIME之間的映射關係,並且檢查SMON_SCN_TIME表中的記錄數,該表的記錄數最大是144000條。

 

The new mappingsare then added for the last period (since SMON last updated), and if this isover 144000, SMON will then issue the delete statement:

delete fromsmon_scn_time where thread=0 and time_mp = (select min(time_mp) fromsmon_scn_time where thread=0)

    --SMON進程會把最新的SCN_TIME映射關係寫入SMON_SCN_TIME表,如果該表的記錄數超過144000條,那麼就會執行上面的delete操作,刪除最早的記錄。

 

There will be anexecution of this each time SMON wakes to update smon_scn_time, and if onedeletion does not free enough mappings, then there will be multiple executions.

--SMON進程每次被喚醒都會更新SMON_SCN_TIME表,如果一次delete操作不能釋放足夠的空間映射空間,就會執行多次delete操作。

 

 

三.禁用SMON 進程對SMON_SCN_TIME 表的更新

 

可以設置12500事件停止SMON進程對SMON_SCN_TIME。

 

具體操作如下:

 

SQL> select count(1) from smon_scn_time;

 

 COUNT(1)

----------

     2115

 

SQL> alter system set events '12500trace name context forever, level 10';

System altered.

 

SQL> select sysdate from dual;

SYSDATE

-------------------

2013-03-20 13:06:15

 

SQL> select count(1) from smon_scn_time;

 

 COUNT(1)

----------

     2115

 

SQL> alter system set events '12500 tracename context off';

System altered.

 

SQL> select sysdate from dual;

SYSDATE

-------------------

2013-03-20 13:19:58

 

SQL> select count(1) from smon_scn_time;

 COUNT(1)

----------

     2119

 

 

 

 

四.SMON_SCN_TIME 表相關的2個案例

 

 

4.1 Oracle 9i SMON_SCN_TIME 表被鎖

 

LOCK ON SYS.SMON_SCN_TIME [ID 747745.1]

 

4.1.1 現象

Oracle 9i,SYS.SMON_SCN_TIME 被 SMON 進程已排它鎖佔用,並且鎖不能釋放,導致數據庫出現性能問題,並且SMON_SCN_TIME表中有大量的記錄。

 

SQL> selectcount(*) from sys.smon_scn_time; 

COUNT(*)  ----------  137545  1 row selected.

--正常情況下,9i最多隻能保存1440條記錄。

 

SQL> select object_id from dba_objectswhere object_name = 'SMON_SCN_TIME';  OBJECT_ID  ----------  575  1 row selected. 

SQL> select * fromv$locked_object where object_id = 575; 

XIDUSNXIDSLOT XIDSQN OBJECT_ID SESSION_ID  ---------- ---------- ---------- ---------- ----------  ORACLE_USERNAME OS_USER_NAME PROCESS  ------------------------------ ------------------------------ ------------  LOCKED_MODE  -----------  5 5 1494 575 164  dbadmin 4444350  3  <=Locked in row exclusive mode

 

 

4.1.2 處理方法

 

設置12500事件,停止SMON 進程更新SMON_SCN_TIME表,然後手工刪除表中的記錄。

 

SQL> alter system set events '12500 tracename context forever, level 10';

 

SQL> delete from smon_scn_time;

SQL> commit;

 

SQL> alter system set events '12500 tracename context off';

Now restart the instance.

 

 

4.2 Oracle 10g SMON_SCN_TIME 表頻繁的被delete

 

High Executions Of Statement "deletefrom smon_scn_time..." [ID 375401.1]

 

4.2.1 現象

 

AWR報告顯示smon_scn_time的刪除操作頻繁的被執行。

delete fromsmon_scn_time where thread=0 and time_mp = (select min(time_mp) fromsmon_scn_time where thread=0);

 

    導致這種現象的原因是SMON_SCN_TIME表和表上的索引不一致。需要重建SMON_SCN_TIME上的索引。

 

SQL> analyze table smon_scn_timevalidate structure cascade; analyze table smon_scn_time validate structure cascade * ERROR at line 1 : ORA-01499: table/Index Cross Reference Failure - see trace file

 

4.2.2 處理方法

 

connect / as sysdba drop index smon_scn_time_scn_idx; drop index smon_scn_time_tim_idx; create unique index smon_scn_time_scn_idx on smon_scn_time(scn); create unique index smon_scn_time_tim_idx on smon_scn_time(time_mp); analyze table smon_scn_time validate structure cascade;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章