第六章 模式對象的依賴 -开发者知识库

第六章 模式對象的依賴 -开发者知识库,第1张

6、模式對象的依賴

某些對象的定義引用了其他對象,比如視圖和過程引用了表。因此,對象依賴於他們定義使用的對象。這一章描述了模式對象的依賴,以及Oracle如何自動跟蹤和管理這種依賴。

這一章包含下列主題:

u 依賴發起介紹

u 模式對象依賴解決

u 對象名稱解決

u 共享SQL依賴管理

u 本地和遠程依賴管理


依賴發起介紹

某些類型的模式對象在定義中引用了其他的對象。例如,一個視圖定義為一個引用了表或者其他視圖的查詢。一個過程體包含的SQL可以引用數據庫的其他對象。一個在定義中引用其他對象的對象叫做依賴對象,而被引用的對象叫做引用對象。圖6-1 顯示了依賴對象和引用對象的區別:

圖6-1 可能的依賴和引用模式對象的類型

第六章 模式對象的依賴 -开发者知识库,第2张

如果你修改引用對象的定義,根據修改的類型,依賴對象可能也可能不繼續起作用。例如,如果你刪除了一個表,依賴刪除表的任何視圖都不可用。

Oracle自動記錄對象之間的依賴,這樣可以降低數據庫管理員和用戶管理依賴工作的復雜性。例如,如果你修改了一個表,但有幾個存儲過程依賴它,Oracle在過程下次被引用時(運行或者重新編譯)自動重新編譯依賴過程。

為管理模式對象之間的依賴性,數據庫中的所有對象都有一個狀態:

u 有效(Valid)模式對象是已經編譯的對象,可以在引用時立刻使用

u 無效(Invalid)模式對象必須在使用之前編譯:

? 對於過程、函數和包來說,這意味着編譯模式對象

? 對視圖來說,這意味着視圖必須使用當前數據字典中的定義重新解析

只有依賴對象可以是無效狀態,表、序列和同義詞總是有效的。

如果視圖、過程、函數或包是無效狀態,Oracle可能已經試圖編譯它們,但是發生了錯誤。例如,當編譯一個視圖,其中的基表可能不存在或者沒有對於基表足夠的權限。當編譯一個包,可能遇到一個PL/SQL或者SQL語法錯誤,或者引用對象沒有足夠的權限。模式對象遇到這種問題仍然是無效的。

Oracle自動跟蹤數據庫中定義的改變並在數據字典中記錄相關對象的合適的狀態。

狀態記錄是一個遞歸過程。引用對象狀態的任何改變不僅改變直接依賴對象的狀態,還影響間接依賴對象的狀態。

例如,考慮一個直接引用一個視圖的存儲過程。實際上,存儲過程間接的引用視圖的基表。因而,如果你修改了基表的結構,視圖就變成無效的了,然后會造成存儲過程的無效。圖6-2 顯示了間接依賴:

圖 6-2 間接依賴

第六章 模式對象的依賴 -开发者知识库,第3张


模式對象依賴解決

當一個模式對象在SQL語句中直接或間接引用一個對象,Oracle根據需要會檢查SQL語句中顯示指定的對象或其他引用對象的狀態。Oracle采取的行動依賴於在SQL語句中直接或間接指定的對象狀態:

u 如果每個引用對象都是有效的,那么Oracle會立刻運行SQL語句,不用任何額外的工作。

u 如果引用的視圖或者PL/SQL程序單位(過程、函數或包)無效,然后Oracle自動嘗試編譯對象:

? 如果一個無效對象能夠成功編譯,然后Oracle就會編譯它們,然后執行SQL語句

? 如果一個無效對象不能成功編譯,那么它還是無效的。Oracle返回一個錯誤並回滾失敗的SQL語句。事務的剩余部分不做改變,可以被用戶提交或者回滾。

注意:無效對象被檢測為無效之后,只有在沒有被替換的情況下,Oracle才會試圖動態的重新編譯無效對象。這個優化減少了不需要的重新編譯。


視圖和PL/SQL程序單位的編輯

視圖或者PL/SQL程序單位只有在滿足下列條件下才會編譯,並生效:

u 視圖或程序單位的定義必須是正確的。所有的SQL和PL/SQL語句必須是正確組織的。

u 所有的引用對象必須存在和有希望的結構。例如,如果視圖的查詢定義包含一個列,這個列必須在基表中存在。

u 視圖或程序單位的擁有者必須擁有引用對象的必要的權限。例如,如果一個過程的SQL語句要插入一行到一個表中,過程的擁有者必須對引用表有INSERT權限。

視圖和基表

視圖依賴於查詢定義中的基表或引用的視圖。如果查詢定義沒有明確引用的列,例如,SELECT * FROM table,然后查詢定義被展開,保存到數據字典的定義包含當時引用表的所有的列。

如果視圖的基表或引用視圖被修改、重命名或者刪除,然后視圖就是無效的,但是它的定義和包括引用這個無效視圖的權限、同義詞、其他對象以及其他視圖仍保存在數據字典中。

注意:無論什么時候你創建了表、索引、視圖,然后刪除表,依賴表的所有對象都是無效的,包括視圖、包、包體、函數和過程等。

視圖使用一個無效視圖自動會導致Oracle動態編譯這個視圖。替換這個視圖后,視圖可能是有效,也可能是無效的,這跟下列情況有關:

u 視圖查詢定義中引用的基表必須存在。如果視圖的基表重命名或者刪除了,視圖就是無效的,無法使用。引用一個無效視圖會導致引用語句失敗。只有基表重新命名為原始名稱或者重新創立基表視圖才能被編譯。

u 如果基表被修改或者使用同樣列名創建,但是基表中一個或者多個列的數據類型改變了,然后大部分依賴視圖可能成功的重新編譯。

u 如果視圖的基表被修改或者使用至少相同系列的列重建,然后視圖可以是有效的。如果基表使用新列重建而且視圖引用的列不再包含在重建表中,視圖是無效的。最后一個相關情況是在SELECT * FROM table定義的視圖,因為定義在視圖定義時被擴展,並持久的保存在數據字典中。

程序單位和引用對象

當引用對象修改之后,Oracle自動將程序單位失效。例如,假定一個單獨過程包含多個語句引用了表、視圖、其他的單獨過程、公用包過程。在那種情況下,會發生:

u 如果引用表被修改,然后依賴過程無效

u 如果引用視圖的基表被修改,視圖和依賴過程都無效

u 如果引用的單獨過程被替換,然后依賴過程無效

u 如果包體的引用被替換,那么依賴過程就不受影響。但是,如果引用包的定制被替代,那么依賴過程就無效了。這是在一種最小化過程和包引用的對象之間依賴的機制。

u 無論何時你創建了一個表、索引、視圖和刪除表,依賴於表的所有對象都失效,包括視圖、包、包體、函數和過程在內。

數據倉庫的考慮

某些數據倉庫晚上會刪除表的索引來加快事實表的裝載速度。但是基表的索引被刪除,所有依賴視圖都會失效。這意味着其后運行的引用這些視圖的包都無效。

記住無論何時,你創建了表、視圖、然后刪除索引,依賴表的所有的對象都會失效,包括視圖、包、包體、函數、過程。這保護了可更新關聯視圖。

要是的視圖重新生效,使用下列語句之一:

SELECT * FROM vtest;

或者

ALTER VIEW vtest compile;

會話狀態和引用包

每個引用一個包結構的會話都有自己的包實例、包括任何公用和私用變量的持久性狀態、游標和常量。所有的會話包實例包含的狀態在會話的實例包無效和重新編譯之后會丟失。

安全認證

當一個DML對象或系統權限分配給一個用戶或PUBLIC或回收權限時,Oracle會注意到,自動將所有擁有者的依賴對象失效。Oracle將依賴對象失效是為了驗證依賴對象的擁有者還擁有所有引用對象的必須權限。本質上說,Oracle注意到那些不需要重新編譯的對象。只有安全認證需要確認,並不是任何對象的結構需要確認。這種優化降低了不必要的重新編譯,阻止不必要的修改依賴對象的時間戳。


對象名稱解決

SQL語句中引用的對象名稱按照周期分為幾個部分。下面描述了Oracle如何解析對象名稱:

1、Oracle嘗試在SQL語句中限定第一部分的引用名稱。例如,在hr.employees,hr是第一部分。如果只有一部分,那么這部分就是第一部分。

a. 在當前模式下,Oracle搜索名稱符合對象名稱的第一部分的對象。如果沒有找到這樣的對象,然后轉向步驟b。

b. Oracle查找公用同義詞來匹配名稱的第一部分。如果沒有找到,然后轉向步驟c。

c. Oracle查找一個模式名字匹配對象名字第一部分的模式,如果找到了,然會步驟b,現在使用名稱第二部分在匹配模式中尋找。如果第二部分不能在前面匹配的模式中找到對象,或者沒有第二部分,Oracle會返回一個錯誤。

如果步驟c無法找到模式,那么對象無法匹配,Oracle返回一個錯誤。

2、模式對象已經匹配,任何剩余的名字部分都要匹配找到的對象的有效部分。例如,如果hr.employees.department_id是名字,然后hr作為模式匹配,employees匹配表,department_id必須對對應列(因為employees是表)。如果employees匹配一個包,那么department_id必須對應一個那個包的公用常量、變量、過程或函數。

因為Oracle解決引用的方式,很可能一個對象依賴於其他不存在的對象。依賴對象使用的引用采取不同的翻譯方式就會是另一個對象,就有可能發生這種情況。


共享SQL依賴管理

在模式對象之間的依賴管理之外,Oracle還在共享池中管理每個共享SQL區域的依賴。如果一個表、視圖、同義詞或者序列被創建、修改或刪除、或者一個過程或包規范被重新編譯,所有依賴它們的共享SQL區域都無效。在對應於一個無效共享SQL區域的游標的隨后執行中,Oracle會重新分析SQL語句來產生新的共享SQL區域。


本地和遠程依賴管理

依賴跟蹤和完成必要的重新編譯是Oracle自動執行的,本地依賴管理指的是Oracle在單獨數據庫中對象中管理依賴。例如,一個過程中的語句能夠引用同一個數據庫的表。

遠程依賴管理指的是Oracle跨網絡在一個分布式環境中管理依賴。例如,一個Oracle表格觸發器可以依賴數據庫中的一個對象。在分布式環境中,一個本地視圖定義的查詢可以引用遠程表。


管理本地依賴

Oracle使用數據庫內部依賴表來管理所有的本地依賴,內部依賴表保存了每個模式對象的依賴對象。當一個引用對象被修改,Oracle使用依賴表來標識依賴對象,這些對象被標識為無效。

例如,假設一個存儲過程UPDATE_SAL引用了表JWARD.employees。如果表的定義被以任何方式修改,每個引用JWARD.employee的對象狀態都改為INVALID,包括存儲過程UPDATE_SAL。因此,這個過程不能運行 ,直到它被重新編譯狀態變為有效為止。類似的,當一個用戶被撤銷了DML權限,用戶模式下的每個依賴對象都無效。但是,一個由於認證被撤銷導致的對象失效只要重新認證就可以重新生效,在這種情況下,不需要全部重新編譯。


管理遠程依賴

Oracle還管理應用對數據庫和分布數據庫的依賴。例如,一個Oracle表格應用程序可能包含一個觸發器,觸發器指向一個表,或者一個本地存儲過程可能調用在一個分布式數據庫環境中的過程。數據庫環境必須說明這些對象之間的的依賴。Oracle根據包含對象的不同,使用不同的機制來管理遠程依賴。

本地和遠程數據庫過程之間的依賴

在分布式數據庫環境中的存儲過程、函數、包、觸發器之間的依賴使用時間戳校驗或簽名校驗。

動態初始化參數REMOTE_DEPENDENCIES_MODE指定是否時間戳或簽名管理遠程依賴。

時間戳管理

在時間戳校驗依賴模型中,無論合適一個過程被編譯或者重新編譯,它的時間戳(創建、修改和替代的時間)在數據字典中都會保存。時間戳是記錄過程創建、修改和替代的時間。另外,過程的編譯版本包含它引用的每個遠程過程的信息,包括遠程過程的模式、包名稱、過程名稱和時間戳。

當使用了一個依賴過程,Oracle將遠程引用過程的當前時間戳和編輯時保存的遠程時間戳。依據這種比較,會發生兩種情況:

u 如果時間戳匹配,本地和遠程過程不需要編譯,直接運行

u 如果遠程引用過程時間戳不匹配,本地過程無效,調用環境返回一個錯誤。此外,所有其他依賴遠程的新時間戳過程的本地其他過程都無效。例如,假設多個本地過程調用一個遠程過程,而遠程過程重新編譯了。當一個本地過程運行,並注意到遠程過程的不同時間戳,每個依賴遠程進程的本地過程都無效。

在本地過程體的語句中調用遠程過程時發生實際時間戳比較。只有在這個時候,時間戳比較才使用分布式數據庫的通訊連接。因而,先於無效過程的本地過程的所有語句可以成功運行。無效過程調用的隨后的語句無法運行。需要重新編譯。

依賴於如何調用無效過程,在無效過程調用之前的DML語句需要回滾。如下所示,隨着整個PL/SQL塊改變被回滾,UPDATE結果也被回滾。

BEGIN

UPDATE table set ...

invalid_proc;

COMMIT;

END;

但是,如下所示,UPDATE結果是正常的,之后PROC調用被回滾。

UPDATE table set ...

EXECUTE invalid_proc;

COMMIT;

簽名校驗

Oracle使用簽名來提供遠程依賴的額外能力。簽名能力只影響遠程依賴。本地依賴是不受影響的,因為這種情況下總可能重新編譯。

過程的簽名包含下列項的信息:

u 包、過程或函數的名稱

u 參數基本類型

u 參數樣式(IN、OUT、IN OUT)

注意:只有參數的類型和樣式是有意義的。參數的名字不影響簽名。

如果簽名依賴模式起作用了,如果依賴單位包含一個父單位中的一個過程的調用,並且這個過程的簽名以一種不兼容的模式修改了,對於遠程程序單位的依賴會導致依賴單位的無效。程序單位可以是包、存儲過程、存儲函數或者觸發器。

其他遠程模式對象的依賴

Oracle並不管理遠程模式對象的依賴,只管理本地過程到遠程過程的依賴。

例如,假設本地視圖被創建,定義中的查詢引用了一個遠程表。還假設本地過程包含的SQL語句引用了同名的遠程表。然后,表的定義被修改。

因此,本地視圖和過程無法生效,即視圖或過程在表被修改之后使用,甚至現在使用視圖或過程還會返回錯誤。在這種情況下,視圖或過程必須手動修改,這樣才不會返回錯誤。在這種情況下,依賴管理的不足會導致不必要的重新編譯依賴對象。

應用程序依賴

數據庫應用程序的代碼可以指向連接數據庫引用的對象。例如,OCI和預編譯應用程序可以提交匿名PL/SQL塊。Oracle表格應用程序的觸發器可以指向一個模式對象。

這些應用程序依賴它們引用的模式獨享。依賴管理技術根據開發環境而不同。

最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复