1、概念數據庫
若是一個對象的定義中引用了其餘對象,那麼此對象被稱爲依賴對象(dependent object),此對象所引用的對象被稱爲引用對象(referenced object)。爲了管理方案對象(schema object)間的依賴關係,Oracle 須要記錄全部的方案的狀態(status):併發
有效的(valid)已經經過編譯,能夠在被引用時直接使用。oracle
無效的(invalid)必須在使用以前進行編譯。分佈式
INVALID狀態對於過程,函數和包來講,這意味着對其進行編譯函數
INVALID狀態對於視圖來講,這意味着此視圖必須使用引用對象(referenced object)當前在數據字典中的定義信息從新進行語法分析(parse)。測試
狀態記錄是一個遞歸的過程。引用對象(referenced object)的狀態變化不只會致使其直接依賴對象(directly dependent object)的狀態變化,同時會影響其間接依賴對象(indirectly dependent object)的狀態。對象
當一個方案對象(schema object)在 SQL 語句中被直接引用或被此語句中的依賴對象(dependent object)所引用(間接引用)時,Oracle 均會在須要時對其狀態進行檢查。SQL 語句中被直接或間接引用的對象的狀態決定了 Oracle 的後續操做:blog
1)若是 SQL 語句中全部的引用對象(referenced object)均處於有效狀態,則 Oracle 無需進行其餘工做就能夠直接執行 SQL 語句遞歸
2) 若是 SQL 語句中存在無效的引用(referenced)視圖或 PL/SQL 程序結構(過程,函數,或包),Oracle 將自動地嘗試編譯這些對象ci
引用對象修改後可能出現的狀況以下:
若是引用表被修改,則依賴過程(dependent procedure)將處於無效狀態
若是引用視圖的基表(base table)被修改,則此視圖及依賴過程都將處於無效狀態。
若是引用獨立過程被替換(replace),則依賴過程將處於無效狀態。
若是引用包的定義(body)被替換,則依賴過程不受影響。可是當引用包的聲明(specification)被替換後,依賴過程將處於無效狀態。這是一種利用包來減小過程與引用對象之間依賴性的機制。
在分佈式數據庫系統中,函數,包,觸發器等存儲過程間的依賴性是經過時間戳檢查(time stamp checking)或特徵標識檢查(signature checking)來進行管理的。
時間戳檢查
在時間戳檢查模式下,一個過程被編譯或重編譯時的時間戳(即一個過程被建立,修改或替換的時間)將被記錄在數據字典中。同時還將記錄此過程的版本信息,包括此過程所引用的全部遠程過程的所屬方案,包名稱,過程名稱,及時間戳。
當運行一個依賴過程時,Oracle 將對此過程編譯時所記錄的遠程時間戳與遠程引用對象當前的時間戳進行比較。根據比較結果,可能有兩種狀況發生:
若是時間戳比較結果一致,那麼本地及遠程過程均無需編譯就可直接運行。
若是存在時間戳比較結果不一致的遠程引用對象,那麼本地過程將被置爲無效狀態,並向此過程的調用者發送一個錯誤信息。此後,Oracle 還會將全部引用了時間戳發生變化的遠程過程的本地過程置爲無效狀態。例如,多個本地過程當中都需調用一個遠程過程,且此遠程過程進行了重編譯。當一個本地過程開始運行,並發現遠程過程的時間戳有變後,全部依賴於此遠程過程的本地過程都將被置爲無效狀態。
時間戳的比較發生在本地過程當中調用遠程過程的語句執行時。此時 Oracle 纔會使用分佈式數據庫的通訊連接(communications link)對兩個時間戳進行比較。所以,本地過程當中位於無效遠程過程調用以前的語句可能所有運行正常,而以後的語句則根本不會運行。此時必須對本地過程進行重編譯。
在同一個數據庫內,被引用對象上進行了alter、drop等操做,該對象的依賴對象如view、function、procedure等,狀態會自動標記爲Invalid,再從新使用這些依賴對象時,系統會自動從新compile。
而一個數據庫內的對象引用了遠程數據庫的對象(這裏指程序對象,如procedure等),則遠程數據庫對象發生了變動,因爲本地數據庫並不知曉此種狀況,本地數據庫的這些對象狀態仍然爲valid,在調用這些對象時,Oracle會根據remote_dependencies_mode參數值,肯定採用timestamp或signature進行依賴性檢查。若是發現不匹配,則會直接報錯返回,同時將依賴該遠程對象的全部本地對象標記爲invalid。
2、測試存儲過程的last_ddl_time和timestamp什麼時候發生變化
select *
from user_objects u
where u.OBJECT_TYPE='PROCEDURE'
AND U.OBJECT_NAME='PROC_JIFEN_CX'
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP STATUS
PROC_JIFEN_CX [NULL] 559675 [NULL] PROCEDURE 2010-5-5 17:47:58.000 2010-9-16 22:19:31.000 2010-09-16:22:19:31 VALID
/
select *
from user_objects u
where u.OBJECT_TYPE='PROCEDURE'
AND U.OBJECT_NAME='PROC_JIFEN_CX'
/
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP STATUS
PROC_JIFEN_CX [NULL] 559675 [NULL] PROCEDURE 2010-5-5 17:47:58.000 2010-11-5 11:38:09.000 2010-09-16:22:19:31 VALID
/
--存儲過程狀態爲valid,編譯存儲過程,不改變內容,last_ddl_time改變,timestamp不變;
alter table JIFEN_CX_LOG add nyytest number(2)
/
select *
from user_objects u
where u.OBJECT_TYPE='PROCEDURE'
AND U.OBJECT_NAME='PROC_JIFEN_CX'
/
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP STATUS
PROC_JIFEN_CX [NULL] 559675 [NULL] PROCEDURE 2010-5-5 17:47:58.000 2010-11-5 11:38:09.000 2010-09-16:22:19:31 INVALID
--對存儲過程依賴的表進行修改,過程狀態變爲invalid
select *
from user_objects u
where u.OBJECT_TYPE='PROCEDURE'
AND U.OBJECT_NAME='PROC_JIFEN_CX'
/
--存儲過程狀態爲invalid,編譯存儲過程,狀態變爲valid,last_ddl_time和timestamp都改成最新的
---遠程數據庫調用執行報錯ORA-04062: timestamp of procedure "EDU.PROC_JIFEN_CX" has been changed; 過程狀態已爲valid,再次執行成功,last_ddl_time和timestamp都改成最新的
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP STATUS
PROC_JIFEN_CX [NULL] 559675 [NULL] PROCEDURE 2010-5-5 17:47:58.000 2010-11-5 11:42:40.000 2010-11-05:11:42:40 VALID
3、測試package body的last_ddl_time和timestamp什麼時候發生變化
select *
from user_objects u
where U.OBJECT_NAME='PKG_JIFEN_CX_SET'
AND OBJECT_TYPE='PACKAGE BODY'
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP
PKG_JIFEN_CX_SET [NULL] 192968 [NULL] PACKAGE BODY 2010-11-5 11:48:45.000 2010-11-5 11:48:45.000 2010-11-05:11:48:45
---編譯以前狀態爲valid,編譯以後,last_ddl_time變化,timestamp不變
select *
from user_objects u
where U.OBJECT_NAME='PKG_JIFEN_CX_SET'
AND OBJECT_TYPE='PACKAGE BODY'
/
select *
from user_objects u
where U.OBJECT_NAME='PKG_JIFEN_CX_SET'
AND OBJECT_TYPE='PACKAGE'
/
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP STATUS
PKG_JIFEN_CX_SET [NULL] 192968 [NULL] PACKAGE BODY 2010-11-5 11:48:45.000 2010-11-5 11:51:23.000 2010-11-05:11:48:45 VALID
/
alter table JIFEN_CX_LOG add nyytest number(2)
--修改依賴表的表結構,package body狀態爲invalid,package狀態爲valid,遠程數據庫調用包執行正常,且執行事後package body已編譯經過狀態爲valid,last_ddl_time和timestamp都已修改成當前時間
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP STATUS
PKG_JIFEN_CX_SET [NULL] 192968 [NULL] PACKAGE BODY 2010-11-5 11:48:45.000 2010-11-5 11:51:23.000 2010-11-05:11:48:45 INVALID
/
--遠程數據庫調用包執行正常,且執行事後package body狀態爲valid,last_ddl_time和timestamp都已修改成當前時間
OBJECT_NAME SUBOBJECT_NAME OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE CREATED LAST_DDL_TIME TIMESTAMP STATUS
PKG_JIFEN_CX_SET [NULL] 192968 [NULL] PACKAGE BODY 2010-11-5 11:48:45.000 2010-11-5 11:54:55.000 2010-11-05:11:54:55 VALID