Oracle中最容易被忽略的那些實用特性



內容來源:2017 年 04 月 08 日,ITPUB管理版版主呂海波在「DBGeeK+PG數據庫技術沙龍(4月杭州站)」進行《Oracle中最容易被忽略的那些實用特性》演講分享。IT 大咖說(微信id:itdakashuo)做爲獨家視頻合做方,經主辦方和講者審閱受權發佈。sql

閱讀字數:5457 | 14分鐘閱讀數據庫

嘉賓演講視頻及PPT回顧t.cn/RdHo5AI

摘要

本次演講主要圍繞Oracle的幾個特性展開,包括多租戶、In-Memory Option、多LGWP、邏輯讀優化。c#

雲端數據庫:多租戶

多租戶在Oracle中正式名稱是Multitenant Architecture,它包含兩個比較重要的概念CDB和PDB。CDB中的C是Container,所以又被稱爲容器數據庫,PDB的P是Plugged,因此被稱爲可插拔數據庫。緩存

簡單來講,多租戶就是在一個數據庫塞多個數據庫。CDB做爲一個母體,能夠有N個PDB,且至少有1個PDB。全部PDB共享同一個SGA,和一系列的後臺進程。在Oracle中內存加進程被稱爲實例,也就是說對外是一個實例,下方則是多個數據庫。雖然PDB和MySQL的Database看起來相似,可是區別其實很是大。最大的不一樣在於PDB之間是相對獨立的,有獨立的SYSTEM和數據文件,在oracle 12c release 2中UNDO和Redo File也是獨立的。當CDB是OPEN狀態時,每一個CDB能夠是MOUNT、OPEN、OPEN Read Only三種狀態其中之一。bash

其實咱們能夠將CDB、PDB、多租戶理解爲對Oracle表空間遷移的延伸,其主要目的就是爲了讓數據庫獨立,使得遷移更方便。Oracle中表空間遷移有不少的依賴關係,好比A表空間中存在B表空間的索引之類的,因此在遷移的時候不光要遷移目標表空間,還要遷移所依賴的表空間。而在多租戶中PDB是隔離的,所以可以很容易進行遷移。微信

CDB$ROOT

在CDB中有一個CDB$ROOT的根PDB,它是一個獨立數據庫。它的數據字典中包含其餘PDB的信息,因此拔出某個PDB,能夠說是從一個CDB的CDB$ROOT中拔出。CDB$ROOT中的配置,就是全部PDB的默認配置。修改CDB$ROOT 中的參數、配置,就是在整個CDB級修改。Oracle準備了一個保存全部PDB信息的數據字典視圖dba_pdbs,經過它就能夠查詢當前一共有多少PDB。session

select pdb_id, pdb_name, dbid, con_uid, guid, status, con_id from dba_pdbs複製代碼

上圖是經過這條SQL語句得到的查詢結果。能夠看到這裏面是不包含CDB$ROOT的,其實這個母體是存在的,可是Oracle爲了不誤操做將它給隱藏了。數據結構

PDB_PDB$SEED

除了CDB$ROOT,還有一個PDB_PDB$SEED——種子PDB,它只能以只讀模式打開,不能手動關閉,只能隨CDB$ROOT一塊兒打開或關閉。它讓你可以直接經過Clone PDB$SEED來建立新數據庫。它只包含SYSTEM表空間和SYSAUX表空間,並且咱們不能增減它的表空間,也不能在它裏面建立表、索引等對 象。同時PDB$SEED只用來做Clone操做時的源,沒法對它進行任何操做。併發

多租戶:建立CDB

建立CDB有兩種方式。一種是使用DBCA,目前都建議使用這種方式。一種手動建立。oracle

上圖是手動建立的步驟,要注意的是標紅區域。其中enable pluggable database用來啓用CDB,後面的部分是用來指定種子PDB的存儲位置。seed file_name_convert是兩個選項,SEED和FILE_NAME_CONVERT。建庫命令中所建立的SYSTEM、SYSAUX等等表 空間、數據文件都屬於根PDB CDB$ROOT,seed選項是聲明建立PDB$SEED。Oracle會從CDB$ROOT Clone SYSTEM表空間和SYSAUX表空間來建立PDB$SEED,file_name_convert選項指定Clone表空間時新數據文件的位置。此選擇的做用和用法相似Standby中的file_name_convert。

多租戶:建立新的PDB

在CDB中建立新PDB,只須要使用這條SQL語句

CREATE PLUGGABLE DATABASE pdbtest1 ADMIN USER dba1 IDENTIFIED BY a 
file_name_convert=('/export/home/oradb/oradata/CDBV3/pdbseed/','/export/home/oradb/oradata/CDBV3/pdbtest1/')複製代碼

該語句最後是聲明文件位置,第一個位置參數是種子的文件位置,第二個位置參數是性的PDB的文件位置。

也可使用下面這條語句來建立。

CREATE PLUGGABLE DATABASE pdbtest2 FROM pdbtest1 
file_name_convert=('/export/home/oradb/oradata/CDBV3/pdbtest1/','/export/home/oradb/oradata/CDBV3/pdbtest2/');複製代碼

與上一條語句不一樣,這裏是從某一個已經存在的PDB中克隆,因此第一個參數是PDB的位置參數。這種狀況通常用來測試,測試的時候須要儘可能真實的線上數據,在對線上PDB克隆以後,能夠將克隆的PDB拔出再插到測試環境中。

多租戶:鏈接PDB

鏈接到PDB也有兩種方式。一種是先進入cdb$root,再alter session set container=....,進入指定PDB。這種方式相似於MySQL,先鏈接上去,再經過use選擇database。

第二種方式直接鏈接PDB(須要用到監聽),使用tns_name直接進入指定的PDB。

監控

Oracle監聽其實是經過解析實例名來鏈接到某個數據庫。在多個PDB共用一個實例的狀況下,Oracle有一個PMON進程針對公共的實例將多個PDB註冊成服務形式,連個某個PDB的時候,Oracle會經由對應關係來找到實例。

多租戶:數據字典視圖

Oracle與MySQL相比有一個很大的優點,就是數據字典很是豐富。原先Oracle有三層視圖,分別是DBA系列視圖(查看全部數據)ALL系列視圖(可操做數據),USER系列視圖(所屬用戶視圖)。如今在這三層之上多了一個CDB_系列視圖,功能與原先的DBA相同,而原先的DBA視圖降級到PDB這一層。

打開和關閉PDB

如今若是使用bash-3.2$ sqlplus / as sysdba這樣的方式打開數據庫,就只是打開了CDB$ROOT和PDB$SEED,新建立的PDB是不會啓動。

而要想打開其餘PDB須要在打開數據庫後啓動以下命令。

alter pluggable database PDB_NAME1[,PDB_NAME2,……] open [READ ONLY FORCE] [UPGRADE [RESTRICTED]]
alter pluggable database PDB_NAME1[,PDB_NAME2,……] close [immediate]複製代碼

參數管理

整個CDB只有一個SPFILE參數文件,有些參數在各個PDB中能夠設置爲不一樣值。Spfile中只保存CDB的參數值(或者說只保存CDB$ROOT的值),各PDB的參數值是保存在CDB的數據字典中。若是在某一個pdb中create pfile from spfile,結果文件中將只包含此pdb和CDB不一樣的參數(也就是單獨在此pdb中 修改了的參數)。

並不是全部參數都可以在PDB中修改,如內存相關參數,因爲全部PDB會共享SGA,沒法限制某個PDB的內存使用狀況。所以,沒必要要也不能修改某個PDB的內存參數,只能在CDB$ROOT中修改(或者說,只能在CDB級別修改)。

表空間管理

能夠在PDB中建立表空間,每一個PDB中的數據文件、表空間都是獨立的。多個PDB可使用同 一表空間名。查詢DBA_視圖,只能看到當前PDB的信息。

但若是在CDB$ROOT中查詢V$視圖,能夠看到全部PDB中表空間的信息。所以V$視圖中會增長CON_ID列,DBA_視圖中則沒有此列。這是由於每一個PDB本身的SYSTEM表空間中保存本身的數據字典,所以DBA_視圖只有某個PDB的信息。而V$視 圖中的信息則來自於控制文件,控制文件是全部PDB共享的。

用戶、角色、權限

因爲有了CDB和PDB,因此用戶被分爲兩類,一類跨越全部PDB的用戶,也叫全局用戶,一類只存在某個PDB內的Local用戶。Oracle中全局用戶必須以c##開頭,須要注意的是雖然Public不以c##開頭,但它也是一個全局用戶,在每一個pdb中能夠授於Public不一樣的權限。

與用戶管理同樣,角色也有全局和Local之分,同一Common role,在不一樣PDB中能夠有不一樣的權限。

全局用戶在不一樣PDB中也能夠有不一樣的權限,經過CONTAINER=current|ALL能夠控制權限是針對當前PDB仍是全部PDB。

NoCDB轉換成CDB

// 一、以受限模式打開數據庫:
shutdown immediate;
startup restrict mount exclusive;
alter database open read only;

// 二、生成XML元數據描述文件:
begin
dbms_pdb.describe(PDB_DESCR_FILE => '/u02/noncdb/orcl.xml');
end;

// 三、建立PDB
create pluggable database orcl using '/u02/noncdb/orcl.xml' copy;

// 四、執行noncdb_to_pdb腳本
alter session set container=orcl;
@?/rdbms/admin/noncdb_to_pdb.sq複製代碼

In-Memory Option

In-Memory Option是Oracle 12C中的一個重要特性,它開闢了一塊大小1m的內存空間IMCU。表的數據以列爲單位保存在IMCU中,一個表至少佔一個IMCU。

開啓In-Memory Option,首先要設置In-Memory Option的大小,而後重啓下數據庫。

//這裏設置In Memory Area大小爲100m
SQL> alter system set inmemory_size=100m scope=spfile;

//加載表到IM中:
SQL> alter table t2 inmemory;

//取消In-Memeroy Area中的表
SQL> alter table t2 no inmemory;複製代碼

存儲索引

Oracle將每一個IMCU中最小ID值和最大ID值,保存到一塊專門的內存區域,這個內存區就是存儲索引。全表掃描的時候會先在存儲索引中過濾一遍,過濾出只須要掃描的IMCU,好比查詢條件是ID>20 and ID<=100的列值,圖中第二個IMCU中,ID值的範圍是410~600,它就將被過濾掉。

多LGWR

Oracle的LGWR進程是用來將Log Buffer中的緩存寫入文件中。一直到oracle 11g release 2版本LGWR進程都只能有一個,單進程在壓力高的時候是會有延遲的,多LGWR有效的環節了這一問題。

多LGWR模式下LGWR再也不進行寫操做,而是交給了LG0和LG1進程(優先使用LG)。在Log Buffe中有多個子池,通常只要其中的某一個子池數據超過三分之一,LWGR就會認爲負載足夠大了,這是會啓用LG1。

多LGWR模式下存在一種特殊狀況,即LG1先完成了I/O,但事務還有部分Redo沒有寫到磁盤,這時LG1會等待「 LGWR intra group sync」事件。前臺進程將繼續等待 Log File Sync。

邏輯讀時鎖的變化

邏輯讀在Oracle和MySQL中很類似,右下方區域在Oracle中被稱爲塊,保存着實際數據。

邏輯讀中會先根據塊的編號之類的信息進行hash運算找到鏈表,再在鏈表中搜索對應的數據結構,數據結構中就存放着塊的內存地址。整個過程當中不少共享資源須要鎖來保護,因此邏輯讀的性能和併發主要就是看鎖的設計。

在MySQL中是不保護hash表的,它保護的是鏈表、buf_block_t以及下方的塊。而Oracle中則是多個鏈表(通常爲四、5個)由1個鎖保護。

(獨佔模式)

(共享模式)

Oracle經過CBC Latch來保護鏈表,要訪問鏈表須要先得到它,而後搜索鏈表找到某一個BH,最後在BH中得到BA地址。在之前的版本中CBC Latch只有持有和不持有模式,也就是說沒有共享的狀況,直到最新版本中才有了共享、獨佔模式。

共享模式主要是經過在BH中添加Fast CR PIN來實現,每多一我的讀,引用計數就會加一。

新的機制查詢操做時鎖開銷更低,讀與讀徹底再也不阻塞,提升併發,CBC Latch競爭是Select與DML和CR塊間的競爭。Select間不會再有CBC Latch競爭。競爭優化的重點是縮短DML執行時間、減小事務持續時間(儘快提交)。

相關文章
相關標籤/搜索