Oracle EBR 基於版本重定義

sjw1933 發表於 2022-11-24
Oracle

第一部分 什麼是EBR(基於版本的重定義)

一個經常被忽視的高可用性挑戰是應用程式升級。應用程式升級涉及對應用程式資料庫物件的邏輯方面所做的任何變更。大型任務關鍵型應用程式無法承受任何停機時間,即使對於計劃內維護(如應用程式升級)也是如此。因此,迫切需要零停機時間的應用程式升級。

EBR (基於版本的重定義)* 功能到來前物件只有一個版本,透過*OWNER.OBJECT_NAME 引用,在有EBR 之後,一個物件有多個版本,可以透過切換會話來使用不同版本。在升級過程中,可以在新版本中修改程式碼,賦權,測試,累積這些變化,最後再資料庫層面修改預設版本為新的版本即可。

為什麼使用基於版本的重新定義  (EBR)?

很多重要應用程式不允許停機。此要求從硬體一直延伸到應用程式。因此,每次維護都必須線上,即零停機時間。EBR  具有以下主要優點,可最大限度地減少應用程式升級的停機時間:

           允許 對資料庫中應用程式記錄一組構件進行任意更改

           同時利用 升級前和升級後的應用程式 (熱切換)

           跨版本保持 應用程式的不間斷可用性 (實時操作)

           確保 不會對效能產生明顯的負面影響

第二部分 EBR基本概念

基於版本的重新定義   (EBR)  的元件

使用  EBR  需要了解各種元件及其功能。

1. 版本

版本是沒有任何所有者的非架構物件型別,是  Oracle  資料庫的內建功能。任何資料庫都必須至少有一個稱為基本版本(即  ora$base )的版本。建立的任何新版本都是現有版本的子版本,每個版本只能有一個子版本。每個資料庫會話都使用基本版本。更改會話命令允許會話更改其版本。

管理員通常使用版本作為  EBR  的一部分來執行:

      在新版本的環境中安裝程式碼變更

      透過寫入新列 / 表安全地更改資料

      遮蔽舊版本或其他版本使其看不到更改

2. 版本檢視

在定義版本檢視之前,瞭解版本化物件型別與非版本化物件型別的概念顯得非常重要。 Oracle  資料庫中支援的各種物件大致可分為兩類:

1.      版本化物件 –  既繫結到 schema,也繫結到版本。檢視、同義詞和所有型別的 PL/SQL 物件(如觸發器、函式、庫、包和包體、過程、型別和型別主體)都是版本化物件型別。所有其他物件型別都是非版本化的。

2.      非版本物件 –  對所有版本可見,並且不繫結到特定版本。表和索引是非版本化物件型別的示例。

版本檢視是一種特殊型別的檢視,是一種版本化物件。版本控制檢視從單個基表中選擇列的子集,並選擇性地為它們提供別名。在提供別名時,版本檢視將物理列名(由基表使用)對映到邏輯列名(由應用程式使用)。將版本檢視視為表的  API 。由於可以對版本檢視進行版本化,因此它們允許您將其基表視為子表本身已進行版本化,並允許在不同版本中呈現其邏輯投影的不同例項。

管理員通常使用版本檢視作為 EBR 的一部分來:

      在每個版本中公開表的不同投影

      允許每個使用者只檢視自己的列

3. 跨版本觸發器

與受  DML  操作限制的普通檢視(資料庫物件型別)不同,版本檢視既可以是隻讀的,也可以是讀寫的。如果在基表上定義了跨版本觸發器,則使版本控制檢視為可讀寫而不是隻讀。跨版本觸發器是一種特殊型別的觸發器,它是一種版本化物件型別。跨版本觸發器必須始終由啟用版本的使用者擁有,因此始終是版本觸發器。跨版本觸發器直接在基表上建立,而不是在版本檢視上建立。有兩種型別的跨版本觸發器,如下所示。

1.      轉發跨版本觸發器 –  透過將任何舊版本中所做的資料更改複製到新版本來確保資料一致性。當連線到應用程式的升級前版本的會話發出 DML 語句時,通常會觸發此語句。

2.      反向跨版本觸發器 –  透過將任何新子版本的資料更改複製到舊版本中來確保資料一致性。當連線到應用程式的升級後版本的會話發出 DML 語句時,通常會觸發它。

通常使用跨版本觸發器作為 EBR 的一部分,以便:

      透過使用轉發跨版本觸發器,將任何舊版本所做的資料更改傳播到新版本的列中。這是最常見的用例。

      透過使用反向跨版本觸發器,將任何新子版本所做的資料更改傳播到舊版本的列中。

基於版本的重新定義  (EBR)  用例

以下是  EBR  可用於在應用程式升級期間維護應用程式可用性的典型用例。需要一次性配置步驟才能為資料庫啟用 EBR

 

第三部分 簡單用例演示

-- 建立使用者DEMO
SQL> create user demo identified by demo;
User created
 
-- 賦予連線和建立過程許可權
SQL> grant create session, create procedure to demo;
Grant succeeded.
 
-- 建立新版本version2,作為ORA$BASE的子版本。ORA$BASE是系統預設的版本
SQL> create edition version2 as child of ora$base;
Edition created.
 
-- 切換到DEMO使用者, 此時使用的是預設版本
SQL> connect demo/demo
Connected.
 
-- 建立過程my_procedure和my_procedure2
DEMO> create or replace
procedure my_procedure
as
begin
   dbms_output.put_line
   ( 'I am version 1.0' );
end;
  /
 
Procedure created.
 
DEMO> create or replace
procedure my_procedure2
as
begin
   my_procedure;
end;
  /
 
Procedure created.
 
-- 預設版本中執行,輸出1.0
DEMO> exec my_procedure2
I am version 1.0
 
PL/SQL procedure successfully completed.
 
-- 切換到DBA使用者
DEMO> connect / as sysdba
Connected.
 
-- 建立新使用者SCOTT
SQL> create user scott identified by tiger;
 
User created.
 
SQL> grant create session to scott;
 
Grant succeeded.
 
-- 為使用者DEMO啟用版本
SQL> alter user demo enable editions;
 
User altered.
 
-- 允許使用者DEMO使用版本version2
SQL> grant use on edition version2 to demo;
 
Grant succeeded.
 
-- 允許使用者SCOTT使用版本version2
SQL> grant use on edition version2 to scott;
 
Grant succeeded.
 
-- 切換到DEMO使用者
SQL> connect demo/demo
Connected.
 
-- 切換到版本version2
DEMO> alter session set edition = version2;
 
Session altered.
-- 此時可看到2個過程,整合至預設版本ORA$BASE
DEMO> 
select object_name,
         object_type,
         status,
         edition_name
from user_objects;
OBJECT_NAME      OBJECT_TYPE             STATUS  EDITION_NAME
---------------- ----------------------- ------- ----------------
MY_PROCEDURE     PROCEDURE               VALID   ORA$BASE
MY_PROCEDURE2    PROCEDURE               VALID   ORA$BASE
 
-- 修改過程my_procedure,版本為2.0
DEMO> create or replace
procedure my_procedure
as
begin
   dbms_output.put_line
   ( 'I am version 2.0' );
end;
 /
 
-- 過程my_procedure已變為VERSION2
DEMO> 
select object_name,
         object_type,
         status,
         edition_name
from user_objects;
OBJECT_NAME      OBJECT_TYPE             STATUS  EDITION_NAME
---------------- ----------------------- ------- ----------------
MY_PROCEDURE2    PROCEDURE               VALID   ORA$BASE
MY_PROCEDURE     PROCEDURE               VALID   VERSION2
 
-- my_procedure在版本version2中已經實體化了,不再是指向父版本的連結
DEMO>
select object_name,
   edition_name
   from user_objects_AE;
 
OBJECT_NAME      EDITION_NAME
---------------- ----------------
MY_PROCEDURE     ORA$BASE
MY_PROCEDURE2    ORA$BASE
MY_PROCEDURE     VERSION2
 
-- 賦予SCOTT使用者my_procedure2執行許可權
DEMO> grant execute on my_procedure2 to scott;
 
Grant succeeded.
 
-- 由於許可權變化,這會引發my_procedure2在版本version2中實體化
DEMO>
select object_name,
         object_type,
         status,
         edition_name
    from user_objects;
 
OBJECT_NAME      OBJECT_TYPE             STATUS  EDITION_NAME
---------------- ----------------------- ------- ----------------
MY_PROCEDURE     PROCEDURE               VALID   VERSION2
MY_PROCEDURE2    PROCEDURE               VALID   VERSION2
 
DEMO> select object_name,
   edition_name
   from user_objects_AE;
 
OBJECT_NAME      EDITION_NAME
---------------- ----------------
MY_PROCEDURE     ORA$BASE
MY_PROCEDURE2    ORA$BASE
MY_PROCEDURE     VERSION2
MY_PROCEDURE2    VERSION2
 
-- 確認當前版本為VERSION2
DEMO> 
SELECT SYS_CONTEXT
  ('userenv',
   'current_edition_name') sc
   FROM DUAL;
 
SC
--------------------------------------------------------------------------------
VERSION2
 
-- 確認執行的是新版本的過程
DEMO> exec my_procedure2
I am version 2.0
 
PL/SQL procedure successfully completed.
 
-- 切換使用者到DEMO
DEMO> connect demo/demo
Connected.
 
-- 確認是預設版本
DEMO>
SELECT SYS_CONTEXT
  ('userenv',
   'current_edition_name') sc
  4  FROM DUAL;
 
SC
--------------------------------------------------------------------------------
ORA$BASE
 
-- 確認執行的是老版本
DEMO> exec my_procedure2;
I am version 1.0
 
PL/SQL procedure successfully completed.
 
-- 切換到SCOTT使用者
DEMO> connect scott/tiger
 
-- 確認是預設版本
SCOTT> 
SELECT SYS_CONTEXT
  ('userenv',
   'current_edition_name') sc
   FROM DUAL;
 
SC
--------------------------------------------------------------------------------
ORA$BASE
 
-- 由於在預設版本里並沒有賦權給SCOTT,因此它無法看到儲存過程
SCOTT> exec demo.my_procedure2
BEGIN demo.my_procedure2; END;
 
      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00201: identifier 'DEMO.MY_PROCEDURE2' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
 
-- 切換到版本version2
SCOTT> alter session set edition = version2;
 
Session altered.
 
-- 由於之前賦過執行許可權,因此可正常執行
SCOTT> exec demo.my_procedure2
I am version 2.0
 
PL/SQL procedure successfully completed.
 
-- 切換到DBA使用者
SCOTT> connect / as sysdba
Connected.
 
-- 在資料庫層面將版本修改為VERSION2,需要重連才生效
SQL> alter database default edition = version2;
 
Database altered.
 
-- 切換到SCOTT使用者
SCOTT> connect scott/tiger
Connected.
 
-- 確認執行的是新版本
SCOTT> exec demo.my_procedure2
I am version 2.0
 
PL/SQL procedure successfully completed.
 
-- 此時系統預設的版本已變為VERSION2,不再是ORA$BASE
SCOTT>
SELECT SYS_CONTEXT
  ('userenv',
   'current_edition_name') sc
       FROM DUAL;
 
SC
--------------------------------------------------------------------------------
VERSION2
 
-- 當然,也可以將版本改回去
SQL> alter database default edition = ORA$BASE;

 

第四部分 常見問題

怎麼實現

在建立新版本時,為了節省時間和空間,新版本中的所有已編輯物件都將被刪除   ,繼承自父版本。換句話說,新版本將使用物件的實際定義   。之前的版本,而不是建立一個新的副本。當物件的定義被更新時,物件被重新定義   ,在新版本中建立新副本,以使前版本中的副本不受干擾的過程   ,在新版本中建立物件的新副本稱為 實現   實現最常用於在安裝需要更新的補丁時更新物件的定義   ,更改物件。有時,使用者可能希望切斷舊副本的繼承,並建立一個   最新版本中物件的獨立副本,即使不更改定義。這創造了一個新的具有相同定義的複製也被稱為 實現

當我刪除舊版本時,繼承的物件會發生什麼? 

繼承物件是當前版本中沒有實現的資料庫物件。它只是一個存根。

 • 如何判斷一個物件是繼承的 ? 基礎物件的哪些變化在後來的版本中是可觀察到的 檢視  ALL_OBJECTS  表,繼承的物件將有一個與當前版本不同的  EDITION_NAME  值。不應該依賴對基對   象進行更改的傳播,比如刪除它。對任何物件的更改都應該在期望更改是可觀察的所有版本中重複。

一個人能使一個物件變成現實嗎 ? 如果可以,繼承物件和實現物件之間是否存在可觀察到的區別 ? DDL 語句 ( 例如 CREATE ALTER DROP) 將實現繼承物件,即使該語句沒有從功能上更改物件。   例如 : 一個被編輯的包可以用  REUSE SETTINGS  子句重新編譯,這將在當前版本中實現包,而不改變它的父   版本。這個包上的依賴物件將在需要時被惰性實現。我們可以透過  dbms_utility.validate() 強制實現依賴包。   透過比較  ALL_OBJECTS  中的  EDITION_NAME  列的值,可以將實現的物件與繼承的物件區分開來。如果   該值與當前版本的名稱相匹配,則為實際。

繼承是透光模式的核心。透光模型是什麼 透光模型指的是,對給定版本中物件的更改可能會反映在屬於後代版本的依賴物件中。這種行為不應該被依   賴,任何預期會在後代版本中看到的更改都應該在每個版本的基礎上重複。

 • 什麼是覆蓋物件 覆蓋物件是一個被編輯的物件,它在任何可用的後代版本中都不再繼承。任何不可用版本中的每個被   覆蓋物件都將被自動計劃的維護過程刪除。

grant是否會導致無效?

  從技術上講, DDL 只能在實際物件上執行 ( 與繼承物件相反 ) 。因此,任何時候在執行  DDL 的會話的當前版本中   繼承的物件上執行一個  DDL ,在  DDL 可以繼續之前,必須首先實現該物件。這一步確實適用於授予。實現對   象的一個直接影響是,它的所有依賴項都必須遞迴地失效,這樣所有依賴項都可以重新編譯,以引用物件的新   副本,而不是舊副本。如果這種行為不受歡迎,有兩種方法可以解決它。   一種方法是在補丁安裝期間提前計劃撥款。這種方法有兩部分。儘可能的, grant  應該在補丁安裝過程中執   行,然後補丁才可以被使用者會話執行。當無法準確預測哪些使用者或角色將獲得授予,但可以預測授予將在哪   些物件上執行時,這些物件可以被先發制人地實現,即使實際授予直到稍後才執行。這將確保所有的實現都   發生在使用者開始使用新版本之前,這樣使用者就不會受到任何失效的干擾。   處理贈款的另一種方法是顯式地尋找作為贈款目標的實際物件。 (User/All/DBA)_Objects  檢視有一列,指定定義   每個已編輯物件的版本。使用 DBMS_SQL   alter session ,授權可以在定義了授權目標的版本中執行。這樣,在   實際物件上而不是在繼承的副本上執行授權將避免任何實現的需要,因此將避免失效。   在任何可能的情況下,應該優先使用先發制人實現物件的第一種方法,而不是在舊版本中執行授予。一般來說,   應該始終認為最好的實踐是隻在最新版本中執行  ddl ,而不是在任何有子版本的版本中執行。

12.2 中掉落版本級聯做了什麼? 

根版本的掉版級聯會判斷版本本身是否為空,那麼它就會標記該版本不可用,一旦版本為空,它就會在後   臺清理該版本。    12.2  之前,如果版本中包含了繼承自後版本的物件,則刪除版本級聯將會出錯。為了更好地控制何時進行清 理,呼叫  DBMS_Editions_Utilities Clean_Unusable_Editions  將立即清理當前在可用版本中沒有繼承的所有物件。

當刪除的版本被清理的時間框架可以被控制以適應特定的時間表嗎?

  最好的做法是讓定期安排的清理過程處理時間範圍。

 • 清理和刪除版本之間的關係是什麼 刪除一個本身是最新版本的版本將導致所有已編輯的物件和版本本身將在 drop edition  語句返回之前被刪除。   如果是最老的版本,則該版本將被標記為不可用, drop edition  語句將立即返回。但是,清理過程會定期清理   所有覆蓋的物件。當版本中的所有物件被清除時,版本本身將被刪除。

到底什麼東西會被清理 ?

定期計劃的清理過程將清理不可用版本中的覆蓋物件。一旦所有被覆蓋的物件被清理,不可用的版本將被   自動刪除。

 • 如果清理和掉落版本實際上是耦合的,那麼在合適的時間做掉落版本是否有意義 目前還不清楚這種方法是否會產生任何好處,而 “drop edition” 語句的排程可能會給程式碼增加一個不必要的   層。最好讓清理過程來處理刪除的版本,除非它導致了具體的問題。

利用物化檢視和虛擬列引用可編輯物件的應用程式應該如何利用 EBR? 

使用 “evaluate Using current edition” 語法將允許物化檢視或虛擬列引用建立物化檢視或虛擬列的會話當前使用   的同一版本中的已編輯物件 (  Sys_Context('USERENV' 'CURRENT_EDITION_NAME') 返回的那個 ) 。物化視   圖或虛擬列將繼續使用這個特定的版本,並將始終使用這個特定的版本,即使從正在使用不同版本的會話查詢  ( 或在物化檢視的情況下重新整理 ) 物化檢視或虛擬列。   為了避免由於陳舊的求值關係而導致的意外行為,物化檢視或虛擬列求值子句應該儘可能透過  ALTER materialized view   ALTER TABLE 命令前滾到最新版本。   通常情況下,如果正在安裝某個特定的補丁或應用程式的升級,它將以某種方式改變定義表示式的結果,那麼   將建立一個新的物化檢視來儲存不同的結果,而不會干擾當前正在執行的應用程式所使用的現有物化檢視。考   慮到偶爾需要建立替換的物化檢視,一般來說,物化檢視應該被編輯檢視、傳統檢視或同義詞覆蓋,以便任何   透過名稱引用物化檢視的應用程式程式碼都將引用一個編輯過的物件,該物件可以在建立替換時更新為指向一個   新的物化檢視。   一個使用者應該維護多少個版本 使用者可以使用刪除版本功能刪除不再使用的舊版本。透過這種方式,資料庫將擁有當前正在執行的應用程式   使用的一個版本,如果正在推出一個補丁或更新,可能還會有一個額外的版本。資料庫中的所有其他版本都   將被先前的 刪除版本 命令標記為不可用。

使用者應該刪除 ORA$BASE 嗎 ? 

在其他舊的、退休的版本可以被刪除之前,有必要先刪除  ORA$Base  版本。 ORA$Base  版本在任何方面都沒有   特別之處,除了它是資料庫第一次建立時給資料庫中一個版本的名稱。我們所有多年來一直愉快地使用基於版   本的重定義的現有客戶都在多年前放棄了  ORA$Base  版本,並沒有因為它而出現任何問題。

放棄跨版本觸發器的最佳實踐是什麼?

跨版本觸發器是具有跨版本可見性的觸發器。它的主要目的是保持資料在不同版本之間的同步。   當版本被刪除時,跨版本觸發器也應該被刪除是有意義的。

•一個跨版本的觸發器可以在兩個以上的版本中顯示嗎 ?

不,跨版本觸發器只能“連結”兩個版本,並且只屬於它實際所在的版本。

•如果一個跨版本觸發器處理已經被刪除的版本,那麼該觸發器是否也會自動刪除 ? 反向交叉版本觸發器呢 ? 它是否會隨著舊版本的刪除而刪除 ?

轉發觸發器被自動丟棄。

在刪除版本之前,應該首先禁用反向觸發器,作為刪除過程的一部分。

LINK是可編輯的嗎? 

目前 (21.3)no


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23825935/viewspace-2925043/,如需轉載,請註明出處,否則將追究法律責任。

相關文章