2021年11月17日 星期三

4. Cache Fusion

Cache Fusion 是 Oracle RAC 特有的機制,意思是 SGA 裡面的 Data Block 可以透過 Internal Connect 在 RAC 的節點之間互相傳輸,藉此減少對 Disk I/O 的頻率,一句查詢的 SQL Statement 在 Single Instance Database 執行與在 RAC Database 執行所經歷的流程略有不同:



select 的語法在 Single Instance Database 執行時,會先到 Buffer Cache 裡面查找是否有需要的資料,如果有,則從 Buffer Cache 獲取資料並回傳結果;如果沒有,則將資料重新從 Disk 讀取出來。如果這句語法是在 RAC Database 執行時,首先一樣會從這個節點的 Buffer Cache 查找是否有需要的資料,與 Single Instance Database 不同的是,當本地節點的 Buffer Cache 沒有需要的資料時, RAC Database 會嘗試的查找其它節點的 Buffer Cache 是否有存放這些資料,如果其它節點有,那麼就將這些資料從其它節點的 Buffer Cache 傳送過來使用,這個動作就叫做 Cache Fusion ,如果所有節點的 Buffer Cache 都沒有這些資料,那麼才會從 Disk 重新將資料讀取出來。


那麼 RAC 節點之間怎麼知道互相的 Cache 裡面有沒有需要的資料 !? 靠的就是 Global Cache Service (GCS) 、 Global Enqueue Service (GES) 以及 Global Resource Directory (GRD) 這三個機制。


Global Cache Service 會於作業系統上產生 LMSn 這個 Process , n 代表數字,表示 LMS 可以有多個 Process (lms0 、 lms1 、 lms2 …) , LMS 的數量由參數 GC_SERVER_PROCESSES 所決定,預設會依據系統 CPU 的數量來調整 GC_SERVER_PROCESSES 。 Global Cache Service 主要的用途是用來紀錄與追蹤 Data Block 的位置以及它所處的狀態。


Global Enqueue Service 會於作業系統上產生 LMD 這個 Process ,用來管理與處理 Global Cache 中與 lock 相關的事務。


Global Resource Directory 主要是用來存放 Global Resource 的資訊,例如 Data Block 的位置、狀態、模式與角色以及 master 的所在地 … 等,這些訊息是經由 Global Cache Service 來更新。 Global Resource Directory 存放在 SGA 裡面,每個節點自己都有一份 Global Resource Directory ,最終由 Global Cache Service 來統合與管理。


在了解了這些 Global Service 之後,接下來就來看看 Cache Fusion 是如何運行的,在進行 Cache Fusion 之前,首先來了解 Global Resource 有哪些角色與狀態。


角色方面分為 Local 與 Global 兩種, Local 表示這個 Data Block 是從這個節點第一次由 Disk 所讀取出來,其它節點都沒有這個 Block Copy 或 Dirty Copy ,當其它節點需要讀取這個 Block 並請求傳輸時,這個時候這個 Block 的角色就會由 Local 轉變為 Global 並且進行傳輸,當 Data Block 轉變為 Global 之後就無法降級為 Local ,因為它已經是在外流動了,所以最終寫入 Disk 的 Dirty Cache 它的角色一定是 Global ,當 Dirty Cache 被寫入後再重新由 Disk 讀取出來,它才會為 Local 。


Global Resource 的模式可以分為三種, NULL (N) 、 Shared (S) 與 Exclusive (X) 。 Null (N) 為普通模式,表示沒有對這個 Block 做任何的請求; Shared (S) 為讀取模式,有讀取 Block 需求的時候必需切換為 Shared Mode ; Exclusive (X) 為排它模式,有修改 Block 需求的時候必需切換為 Exclusive Mode 。


每個 Data Block 都有屬於自己的 Resource Master ,這個 Resource Master 不一定存放在同一個節點當中,例如 Data Block 1 它的 Master 可能在節點 A , Data Block 2 它的 Master 可能在節點 B ,而這些資訊都是存放在 Global Resource Directory 當中,在進行 Cache Fusion 之前,所被請求的 Data Block 都必須去詢問 Master ,然後再由 Master 來發號施令派送,整個流程的核心要角,就是經由 Global Cache Service 來達成。


例如現在有四個節點的 RAC , Instance A ~ D ,目前資料為 1008 的 Data Block 的 Resource Master 在節點 D :



接下來總共有四個情境來進行 Cache Fusion :


  • Read with No Transfer :

1. 首先 C 節點需要讀取 1008 這筆資料, C 節點此時必須向 Global Cache Service 發出讀取資料的請求, Global Cache Service 接收到請求之後,便會找出擁有 1008 這個 Data Block 的 Resource Master ,在此為節點 D ,並告知 Resource Master 節點 C 有讀取資料的請求。

 

2. Resource Master (節點 D) 收到這個請求之後,便會把這個 Resource 的模式由 Null 改為 Shared (N 🡪 S) 並且把 Resource 角色設定為 Local ,然後紀錄在 Global Resource Directory ,最後將這個訊息發送給節點 C ,告知它已經可以取得這個 Resource 的 S Mode 。

 

3. 節點 C 取得這個 Resource 的 S Mode 之後,由於是第一次讀取,所以開始從 Disk 讀取出具有 1008 這筆資料的 Data Block 。

 

4. Disk 將具有 1008 這筆資料的 Data Block Image 發送到節點 C , C 節點得到這筆資料後,自此完成整個讀取的步驟。

 


  • Read to Write Transfer :

1. 此時節點 B 需要把 1008 這筆資料修改為 1009 ,因此先透過 Global Cache Service 向 Resource Master (節點 D) 發出更改資料的請求。

 

2. Resource Master (節點 D) 接收到這個請求之後,知道 1008 這個 Data Block 目前為節點 C 擁有,因此發送訊息給節點 C ,告知它節點 B 需要更改這筆資料,請它把這個 Data Block 送過去給節點 B 。

 

3. 節點 C 接收到傳送 Block 的請求之後,必須先把這個 Data Block 的模式由 Shared 改為 Null (S 🡪 N) ,然後把 Null Mode 的這個 Data Block 發送給節點 B 。

 

4. 節點 B 接收到節點 C 發送過來的 Data Block 之後,由於是做資料的更改,因此必須把這個 Data Block 的模式由 Null 改為 Exclusive (N 🡪 X) ,然後再把 1008 這筆資料修改為 1009 。

 


  • Write to Write Transfer :

1. 這時節點 A 需要把這筆資料修改為 1013 ,同樣的對 Resource Master (節點 D) 發出修改資料的請求。

 

2. Resource Master (節點 D) 收到節點 A 的請求之後,知道這個 Data Block 最終為節點 B 擁有,因此告知節點 B 請它把這個 Data Block Image 傳送到節點 A 。

 

3. 節點 B 收到 Resource Master (節點 D) 的請求之後,必須先把這個 Data Block 的模式由 Exclusive 改為 Null (X 🡪 N) 才可以將它傳送,由於節點 B 是做了資料的變更,這個時候必須做 log flush 的動作,也就是把這筆異動的交易資訊確實的寫入 Transaction Log ,在完成 log flush 之後才能釋放 X 並修改為 N ,然後再把此 Data Block Image 送給節點 A 。

 

4. 節點 A 收到這個 Data Block 之後,就可以把它的模式由 Null 改為 Exclusive (N 🡪 X) ,然後將資料修改為 1013 。

 


  • Write to Read Transfer :

1. 最終由節點 C 再度發出讀取這個 Data Block 的請求。

 

2. Resource Master (節點 D) 接收到這個請求之後,請最後的 Block 擁有者節點 A 將這個 Data Block Image 發送給節點 C 。

 

3. 節點 A 接收到這個請求之後,由於是讀取的請求,所以不用等到 log flush 之後才能傳送 Data Block Image ,此時直接把 Data Block 的模式由 Exclusive 改為 Shared (X 🡪 S) 然後將這個 Data Block 發送給節點 C 。

 

4. 節點 C 接收到這個 Data Block 之後,這個 Data Block 有可能是 log flush 之前的 Block ,或者是已經完成 log flush 的 Block ,這邊節點 C 並不能確定,於是節點 C 會去記錄讀取這個 Data Block 當下的 SCN ,並且把這個訊息反饋回 Resource Master (節點 D) ,表示這個 Block 的最終狀態是處於這個 SCN 下的這個資料,這個用意是為了避免節點 A 發送 Block 時還沒有做 log flush ,萬一交易資料遺失的時候 (Instance Crash) ,至少在 Recovery 的過程當中, Resource Master 會知道在這個 SCN 之下的這個 Data Block 是什麼狀態以及它的資料是什麼,避免資料錯誤。

 


由上述 Cache Fusion 的情境可以知道,每當要做一個動作的時候都必須先去向這個 Resource 的 Master 提出請求,那麼要如何知道某個 Resource 的 Master 是位於哪一個節點 ? 透過查詢 v$gcspfmaster_info 就可以得知:

如果 previous_master 顯示為 32767 表示之前沒有做過 Re-Master 的動作,從 Oracle 11g 開始引進了 DRM (Dynamic Resource Management) 機制,用意是將最常存取這個 Data Block 的節點設定為這個 Resource 的 Master ,減少 Cache Fusion 過程中不斷詢問 Master 的成本。


雖然 Oracle RAC 的 Cache Fusion 機制可以有效的減少 Disk I/O ,但這也是一個雙面刃,由上述情境可以知道, Cache Fusion 需要不斷的詢問 Master 、改變 Resource 的模式 (N 、 S 、 X) 以及傳送 Data Block Image ,過程中可能會發生效能上的問題,引發 gc 相關的等待事件。如果想要避免 gc 的等待事件,最好方法就是減少 Cache Fusion 的發生,將不同 Application 的作業進行節點上的分流,以此減少跨節點的 Block 請求,進而減少 gc 事件的發生。



2021年11月4日 星期四

3. Grid Infrastructure

Oracle RAC Cluster Ware 自從 11g 開始改稱為 Grid Infrastructure ,以原本 RAC Cluster Ware 的架構為基礎做了一些改變,首先是軟體結構的部分,在 Oracle 10g 的時候, Cluster 軟體的安裝位置以環境變數 ORA_CRS_HOME 來表示,而在 11g 的 Grid Infrastructure 當中, Cluster 軟體的安裝位置仍然是以環境變數 ORACLE_HOME 來表示,這個改變讓一開始接觸的使用者來說很容易混淆,因為以往 ORACLE_HOME 都代表著資料庫軟體的位置,現在卻要代表兩種路徑, Database Home 與 Grid Infrastructure Home ,因此官方建議將安裝資料庫軟體與安裝 Cluster 軟體的使用者分開來,建立一個新的使用者 "grid" 來安裝及管理 Grid Infrastructure ,這樣就不會把 ORACLE_HOME 的路徑搞混,當然對於熟悉的 DBA 來說,使用同一個使用者藉由環境變數的切換來管理兩個 Home 路徑也是可以的。


在 Services Daemon 的部分,原本代表 RAC 所啟動的 CSSD 、 CRSD 統一由一個 Oracle High Availability Service Daemon (OHASD) 來管理,原本 /etc/init.d 底下的 init.cssd 、 init.crsd 、 init.evmd 改為只有 init.ohasd ,整個 Cluster 啟動的方式與原本大不同:

整個 RAC 的啟動過程改由 OHASD 所發起, OHASD 會發起四個 agent process , oraagent 、 orarootagent 、 cssdagent 與 cssdmonitor :


  • oraagent : 在 Cluster 啟動的初始階段,不需要 root 權限就可以啟動的 process 由 oraagent 來發起,例如 evmd 、 ASM …等。

  • orarootagnet : 在 Cluster 啟動的初始階段,需要 root 權限來啟動的 process 由 orarootagent 來發起,這邊有 ctssd (Cluster Time Synchronization Service ,節點之間用來校時的 process ,避免節點之間的時間差過大導致 Cluster 出現問題,如果有設定 NTP 來校時的話, ctssd 會進入 Observer Mode 不會產生作用) 、 gnsd (Grid Naming Service Daemon ,為 Grid Plug and Play 的功能所用) ,以及 crsd ,這邊比較特別的是, 透過 crsd 還會再產生出一組 oraagent 與 orarootagent ,原因就是有些 process 必須要在 crsd 啟動之後才能夠產生出來,因此在初始化階段產生完 crsd 之後,再由 crsd 啟用一組 oraagent 與 orarootagent , crsd 底下的 oraagent 主要是用來啟動在 crsd 之後,不需要 root 權限的 process ,例如 Listener 、 Database Instance …等;而 crsd 底下的 orarootagent 則是用來產生在 crsd 之後,需要 root 權限的 process ,例如 vip 與 scan ip 。

  • cssdagent : 用來啟動 cssd daemon 。

  • cssdmonitor : 用來監控 cssd 狀態的 process 。


大體上整個 Grid Infrastructure 的架構可以歸納出,由 OHASD 作為代表來開頭,底下的 process 可以分為需要 root 權限以及不需要 root 權限,需要 root 權限的由 orarootagent 來發起;不需要 root 的則由 oraagent 來發起, cssdagent 與 cssdmonitor 則獨立由 root 發起,透過 log 也可以明顯的觀察到整個啟動的流程:


由 log 當中的 agent 目錄底下,可以看到有 ohasd 與 crsd 兩個目錄; ohasd 目錄底下,可以看到四個目錄,這四個目錄也就分別代表 ohasd 所發起的四個 agent process ;另外在 crsd 目錄底下,也可以看到 oraagent 與 orarootagent 兩個目錄,這也表示由 crsd 所發起的兩個 agent process 。不過 Grid Infrastructure 的 log 到了 Oracle 12c 之後,統一由 $ORACLE_HOME/log (這裡的 ORACLE_HOME 代表 Grid Infrastructure 軟體的 Home 位置) 這個目錄轉移到 ADR 目錄 ($ORACLE_BASE/diag) 底下, Oracle 12c 之後就沒有對這些 log 做這麼詳細的分類了。


在網路結構部分, Grid Infrastructure 增加了一組 SCAN (Single Client Access Name) 的概念,建議將 SCAN 註冊到 DNS 上並且對應 1 ~ 3 組的 IP Address , SCAN 的用意在於,以往每台 RAC 節點都有屬於自己的 VIP , Client 連線必須設定這些節點的 VIP ,如果 Cluster 有新增或是刪除節點,那麼 Client 就要再添加或刪除這些節點的 VIP 設定,而 SCAN 這個概念就是為了減少 Client 端設定的負擔,不論 Cluster 節點怎麼增減, Client 端只要統一使用 SCAN 這個名稱來連線就好,不用隨著節點的 VIP 增減來修改, tnsnames.ora 的設定由以往需要寫入所有的 VIP 改成只要使用一個 SCAN 就好:


對於 Private IP 的設定,在 11.2.0.2 的版本之後多了一組 HAIP (High Available IP) 的概念,以往對於 Internal Connect 要做 Redundancy 都是把兩張網卡 Binding 起來,而 HAIP 的概念就是允許 Internal Connect 可以有兩張或以上的網卡,不需要 Binging 就可以達到 Redundancy 與 Load Balance 的功能,預設 HAIP 這個功能是啟用的,對於 Private IP 來說,會在 Private 網卡上再自行綁定一組 169.254.*.* 網段作為 HAIP 所用,之後節點之間的傳輸就會都透過這組 169.254.*.* 的網段來溝通。如果只有單網卡或者是已經綁定的單一網卡,可以用 root 的身分執行 crsctl stop res ora.cluster_interconnect.haip –init 來停止 HAIP 這個功能,或者是執行 crsctl modify res ora.cluster_interconnect.haip -attr "ENABLED=0" –init 完整關閉 HAIP ,這邊要注意的是,停用或啟用 HAIP 必須所有節點的設定一致,否則有可能造成 RAC Database 無法啟動等問題。


另外的改變就在於 Listener ,在 Oracle 10g 的 RAC 當中, Listener 是由 ORACLE_HOME (Database Home) 所發起的;而在 11g 的 Grid Infrastructure 當中, Listener 是改由 Grid Infrastructure Home 所發起的,如果有建立 grid 這個使用者,那麼 Listener 這個 process 的擁有權將會是 grid 所屬。


Grid Plug and Play 是 11g Grid Infrastructure 的新功能,用意在於能夠讓整個 Cluster 架構快速增加節點,在增加節點之前不需要規劃新節點所要使用的 Hostname 與 VIP ,由系統自行決定新節點的名稱與 VIP ,整個結構是透過 GNS (Grid Name Service) 來達成:


如果要使用 Grid Plug and Play 這個功能的話,首先必須要設定 GNS 服務,需要設定一組 GNS 所使用的 IP 並註冊到 DNS 上,在 GNS 服務啟用之後,新節點的 VIP 與 SCAN IP 會經由 DHCP 來自動分配,同時在 Cluster 架構之內啟用 mDNS (multicast DNS) ,這個可以視為是 Cluster 內部自己使用的 DNS ,用來解析 GNS 架構下的節點名稱。對於 Client 的連線來說, Client 端還是透過 SCAN 來連線,而這個連線首先會導到 GNS , GNS 在接收到連線的請求之後,會把它底下所擁有的節點名稱反饋回 DNS , DNS 在清楚了這些節點之後,再把連線送達到最終的 Server 。


Grid Plug and Play 在理念上是一個很好的設計,然而在實務上使用並不多見,其一是節點名稱與 VIP 由管理者自行規劃顯然是比較好管理的;其二是連線必須多增加一層 GNS 解析,對於整個連線的時間來說還是會有些效能上的影響。


最後在 Storage 結構的部分,最大的改變就是 OCR 與 Voting 可以放置在 ASM 裡面,而 ASM 啟用的方式也由 10g 時候的 ORACLE_HOME (Database Home) 改由 Grid Infrastructure Home 來啟動。


由於 ASM 改由 Grid Infrastructure Home 來啟動,因此在 Oracle 11g 之後如果想使用 ASM 則必須安裝 Grid Infrastructure ,而這邊有個選項,使用 ASM 不一定是要 RAC 架構, Single Instance 的架構下也可以使用 ASM ,只要在單台 Server 上安裝 Grid Infrastructure 就可以,而這個在單台架構下所安裝的 Grid Infrastructure 就稱作 Oracle Restart 。 Oracle Restart 的架構下,也是經由 OHASD 來發起服務,差別只在於 Oracle Restart 只會有 cssd 不會有 crsd daemon ,透過 crsctl stat res –t –init 可以觀察到 Oracle Restart 不會有 crsd :


Oracle RAC 這項技術在 11g 推出了 Grid Infrastructure 之後可以說已經達到了成熟,直到目前 Grid Infrastructure 已經是 Oracle RAC 的代名詞了。

2021年11月2日 星期二

2. RAC 基礎架構

Oracle RAC 在 Oracle 10g 這個版本開始才比較成熟, Oracle自從 10g 開始有了自己的 Cluster Ware ,搭建 RAC 已經不需要仰賴第三方的 Cluster Ware 。在搭建 RAC 之前,首先要求硬體的基本配置如下:

  • 主機的部分要求兩台或兩台以上的 Server ,需安裝 Oracle Cluster Ware 所支援的作業系統。

  • 網路的部分每台 Server 需要設定兩個網段,一個是對外網段 (Public IP) ,用來提供對外服務的連線所用;另一個是對內網段 (Private IP) ,俗稱心跳線,為 Cluster 成員之間聯繫所用。不論是對內或對外網段,都要求作業系統上所設定的網卡名稱必須相同,例如對外網段的網卡名稱為 eth0 ,那麼所有 Cluster Server 上所設定的對外網卡名稱必須都為 eth0 ;同理若是對內網段的網卡名稱為 eth1 ,那麼所有 Server 的對內網段的網卡名稱必須為 eth1 ,由於心跳線對於 Cluster 來說相對重要,如果有問題的話,很容易發生節點驅逐的情況 (Node Eviction) ,一般來說會針對心跳線做 Redundancy ,例如將兩張網卡綁成一張, eth1 與 eth2 兩個綁成一個 bond0 ,避免單點故障,當然綁成 bond0 之後,所有 Server 上也必須都是 bond0 這個名稱。

  • 存儲 (Storage) 的部分要求共享磁碟,也就是說必須設定 Storage 讓所有的 Server 可以共同存取。


在準備好硬體環境之後,便可以安裝 Oracle Cluster Ware 來搭建 RAC , RAC 搭建完成後會有以下的結構,首先是每台 Server 上面都會運行維持 RAC 運作的 Service Daemon ,對於 RAC 來說,有三個重要的 Daemon 必須存在:


  • CSSD (Cluster Synchronization Services Daemon) : 在作業系統上會運行 ocssd 這個 process ,主要的用途是用來偵測 RAC 節點的成員是否存活,以及自己是否為這個 RAC 成員所屬,當 CSSD 有偵測不到的節點時,就會開始發起仲裁行動,將偵測不到的成員進行驅逐。 CSSD 也是 RAC 啟動時最早執行的 Daemon 。

  • CRSD (Cluster Resource Services Daemon) : 在作業系統上會運行 crsd 這個 process , CRSD 可以說是整個 RAC 架構上的本體,為 RAC 的核心 process , CRSD 用來管理 Cluster 上的所有服務,包括 VIP 、 Database Instance 、 Listener 、 ASM …等, RAC 是否成功啟動,就單看 CRSD 是否有正常運行。

  • EVMD (Event Manager Daemon) : 在作業系統上會運行 evmd 這個 process , EVMD 為事件監控程式,當 RAC 的相關 process 發生異常時, EVMD 便會將這些異常的事件紀錄到 log 當中。


這三個 Daemon 是 RAC 最原始的 Process ,在 RAC 安裝完成後,會於 /etc/init.d 底下設定 init.cssd 、 init.crsd 以及 init.evmd ,也就是說在 Server 開機啟動的時候,同時也啟動這些 RAC 的 Process ,如果不想要 RAC 在 Server 開機的時候啟動,那麼就將這些設定註解掉即可。


在網路的部分, RAC 成功啟動後,每台 Server 都會啟動屬於自己的 VIP , VIP 主要是用來提供對外服務的連線所用,因此 VIP 是設定在對外 (Public) 的網段上, RAC 之所以具有高可用性的特性,就是因為有 VIP 的設定,當 RAC 其中一個節點不可用時,其所在的 VIP 便會轉移到其它節點上,讓 Client 的連線可以繼續運行:

VIP 是在 RAC 成功啟動後才會賦予上去的,在安裝階段,每台 Server 需規劃出一組沒有人在使用的 IP Address 作為將來 VIP 所用。


在 Storage 的部分, RAC 架構上有兩個重要的磁碟, OCR 與 Voting Disk :


  • OCR (Oracle Cluster Repository) : 為 Oracle Cluster 的設定檔,用來記錄 CRS 的設定以及其它 Resource 的狀態等資訊,透過 CRS Daemon 來存取與更新。

  • Voting Disk : 仲裁磁碟,在 Oracle 10g 時可以設定一個或三個 Voting Disk ,當 CSS 偵測到異常節點時,用來決定是否將其驅逐 (Eviction) :

例如在 3 個節點的 RAC 當中,其中第三台的心跳線斷線了,因此 Node1 回報說它只認得節點 1 與 2 ; Node2 回報說它也只認得節點 1 與 2 ;而 Node3 只回報說它只認得節點 3 ,經由這些資訊,便可以知道 Node3 與其它節點失去了聯繫,因此最終會將 Node3 進行驅逐 (Node Eviction) 。


OCR 與 Voting Disk 在 Oracle 10g 時還不能存放在 ASM ,必須額外規劃 RAW Disk 來使用,到了 Oracle 11g 之後就都存放在 ASM 了。


搭建 RAC 在 Shared Storage 的選擇上,可以使用 Raw Volumes (但 Oracle 11g 之後已不支援此方式) 、 Cluster File system (例如 IBM GPFS 、 Veritas VCS 、 OCFS2 …等) ,以及 ASM 。 ASM 是 Oracle 為了因應 RAC 需求所獨創的存儲方式,也是目前使用最多、最建議搭配的 Storage 選項,這樣一來從 Database 、 Cluster Ware ,以及 Storage ,都是 Oracle 自有品牌,整個 RAC 的結構也趨於完整。