Oracle Database 12cR2多租户权威指南



Anton Els,Vt pinka,Franck Pachot

Oracle Database 12c
Release 2 Multitenant

EISBN 978-1-25-983609-1

Copyright 2017 by McGraw-Hill Education.

All rights reserved. No part of this publication may be reproduced or transmitted in any form or by any

means, electronic or mechanical, including without limitation photocopying, recording, taping, or any

database, information or retrieval system, without the prior written permission of the publisher.

This authorized Chinese translation edition is jointly published by McGraw-Hill Education and Tsinghua

University Press Limited. This edition is authorized for sale in the People’s Republic of China only,

excluding Hong Kong, Macao SAR and Taiwan.

Translation copyright 2018 by McGraw-Hill Education and Tsinghua University Press Limited.

版权所有。未经出版人事先书面许可,对本出版物的任何部分不得以任何方式或途径复制或传播,

包括但不限于复印、录制、录音,或通过任何数据库、信息或可检索的系统。

本授权中文简体字翻译版由麦格劳-希尔(亚洲)教育出版公司和清华大学出版社有限公司合作出版。

此版本经授权仅限在中国大陆区域销售,不能销往中国香港、澳门特别行政区和中国台湾地区。

版权2018
由麦格劳-希尔(亚洲)教育出版公司与清华大学出版社有限公司所有。

北京市版权局著作权合同登记号 图字:
01-2017-3077

本书封面贴有
McGraw-Hill Education
公司防伪标签,无标签者不得销售。

版权所有,侵权必究。侵权举报电话:
010-62782989 13701121933

图书在版编目(CIP)数据

Oracle Database 12


R2
多租户权威指南
/ (新西兰)安东艾尔斯(Anton Els),
(捷克)维特斯

普林克(Vt pinka),
(瑞士)弗兰克帕丘特(Franck Pachot)
著;史跃东 译.
—北京:清华大学

出版社,
2018

书名原文:
Oracle Database 12


Release 2 Multitenant

ISBN 978-7-302-50251-7

Ⅰ.
①O… Ⅱ.
①安… ②维… ③弗… ④史… Ⅲ.
①关系数据库系统-指南

Ⅳ.
①TP311.138-62

中国版本图书馆
CIP
数据核字(2018)第
103253







责任编辑:
王 军 李维杰

封面设计
牛艳敏

版式设计
思创景点

责任校对:
曹 阳

责任印制:董 瑾

出版发行:
清华大学出版社

网 址:
http://www.tup.com.cn,
http://www.wqbook.com

地 址:北京清华大学学研大厦
A

邮 编:
100084

社 总 机:
010-62770175
邮 购:
010-62786544

投稿与读者服务:
010-62776969,
c-service@tup.tsinghua.edu.cn

质 量 反 馈:
010-62772015,
zhiliang@tup.tsinghua.edu.cn

印 刷 者:北京鑫丰华彩印有限公司

装 订 者:三河市溧源装订厂

经 销:
全国新华书店

开 本:
170mm240mm
印 张:
23
字 数:
451
千字

版 次:
2018

6
月第
1

印 次:
2018

6
月第
1
次印刷

印 数:
1~3500

定 价:
79.80


———————————————————————————————————————————

产品编号:
074808-01



本打算趁着农历春节之前,利用调休的时间将这本
400
多页的书翻译完毕,

谁曾想诸事缠身,一顿忙活之后,也就到了年三十。于是这本书也就只能在春

节之后搞定了。

严格来说,这本书是去年
9
月时着手翻译的,到
2018

2
月,又是
6
个月

的时间。回想起去年翻译《云端存储
Oracle ASM
核心指南》时,也是断断续

续忙了
5
个月才完工。留意起来,才意识到翻译这个活儿,真心是一项费时费

心的工作。平时工作繁忙,也只能挤出晚上或周末,抑或调休的时间进行翻译。

并且书中很多词句都要斟酌再三、反复琢磨,才能够将原文的意思准确表达出

来。免费云主机域名自己写书,是对自己会的知识进行梳理;而翻译,则是研究自己不会的东

西。因此,从某种程度上来说,翻译的过程,实质上也是学习新技术、新知识

的过程。

多租户与
IMO
一道,并称为
Oracle Database 12c
的两大关键特性。此番有

幸从清华大学出版社拿到这本书的翻译权,也是件值得高兴的事情。只不过与


IMO
相关的一本书, 则被
Oracle
原厂拿去翻译了。若是这两本书都由笔者翻译,

再加上前面的
ASM,岂不是完美?可惜。

多租户技术,是
Oracle

12.1
版本开始引入的一项全新特性。它从根本上

改变了
Oracle
数据库长久以来的体系结构,也是
Oracle
在这个风起云涌的时代,

全面迎合云计算的具体表现。对于传统的
Oracle DBA
来说,熟练掌握
12c
版本

中的这一新特性,已经是毋庸置疑的事情。

本书的封底,指出这本书由
OCM
专家团队编写,而实际上,翻阅了本书

前言的各位读者就会知道,本书的三位作者均是
Oracle ACE。他们不仅有着多

年的实践经验,也在各大技术社区和相关会议上进行技术分享。由这样的人撰

写本书, 本书内容的实战性可想而知。本书从多租户的基本概念入手, 涵盖
CDB


PDB
的创建和管理、网络与服务、安全、备份和恢复、数据移动以及多租户

的诸多高级特性,尤其是深入探讨了诸多技术在多租户环境下和此前版本中的

不同之处,这对于我们的实际工作来说,显然是极具价值的内容。

当然,依然要感谢所有在本书付梓出版的过程中给笔者提供帮助的各位人

士,正是你们一直以来的关心与帮助,笔者才能够笔耕不辍、日日向前。

由于笔者才疏学浅,因此在本书的翻译过程中注定会有些错误与不足之处,

各位读者见到后,望不吝赐教。



2018

2

22




Anton Els
是一位
Oracle ACE,目前是
Dbvisit
软件有限公司的高级副总裁。

Anton
在数据库技术领域已经有超过
15
年的工作经验,擅长
Oracle
数据库、备

份和恢复、数据库备库、
Oracle Linux、虚拟化以及
docker
技术。
Anton
是独立

Oracle
用户组(Independent Oracle Users Group,
IOUG)的活跃成员,同时也是新

西兰
Oracle
用户组(New Zealand Oracle Users Group,
NZOUG)的副主席。
Anton

拥有
Oracle Database 11g
OCM
证书,还拥有从
8i

12c
的全部
OCP
证书。同

时,他还拥有
Oracle Database 11g
RAC

GI
管理员方向的
OCE
证书、
Red Hat

5 RHSA
证书,以及
Oracle Solaris 10

SCSA
证书。
Anton
经常出席相关工业

及用户组会议,例如一些行业合作会议、在日本举行的
Oracle OpenWorld
数据

库技术专场会议、
NZOUG,以及亚太和拉美地区的
Oracle
技术网络(OTN)年

会等。可以访问他的
Twitter(@aelsnz)或博客(www.oraclekiwi.co.nz)。

Vt pinka
是一位
Oracle ACE-A, 目前是
Dbvisit
软件有限公司的首席架构

师。
Vt
在数据库技术领域也有超过
15
年的工作经验,主要擅长
Oracle
数据库

技术。
Vt
也是
IOUG
的活跃成员,并经常出席
Oracle OpenWorld、行业合伙


会议、UKOUG、DOAG
以及
NZOUG
的相关活动。Vt
拥有
Oracle Database 10g、

11g
以及
12c

OCM
证书,还拥有从
9i

12c

OCP
证书、Oracle Database 10g

RAC
管理员专家认证,以及
LPIC-2 Linux
网络专业认证。可以访问他的

Twitter(@vitspinka)或博客(http://vitspinka.blogspot.com)。

Franck Pachot
是一位
Oracle ACE
总监,目前是
dbi
服务公司(瑞士)的首席

顾问、培训专家以及
Oracle
技术领导人。
Franck

Oracle
技术领域拥有超过

20
年的工作经验。
Franck
也经常参加
Oracle OpenWorld、
IOUG
合作会议、

DOAG、
SOUG
以及
UKOUG
的活动。他是
SOUG

DOAG
的活跃成员,同

时还是
OraWorld
团队的荣誉成员。
Franck
拥有
Oracle Database 11g

12c


OCM
证书, 还拥有从
8i

12c
的所有
OCP
证书, 同时拥有
Oracle Database 12c

性能管理与优化方向的
OCE
证书。另外,他还拥有
Oracle Exadata Database

Machine 2014
实施认证证书。可以访问他的
Twitter(@franckpachot)或博客

(http://blog.pachot.net)。



Deiby Gmez
是世界上最年轻的
Oracle ACE(23
岁)以及
ACE
总监(25
岁),

同时也是母国危地马拉的第一位
ACE

ACE
总监,还是拉美地区最年轻(24

岁,
2015.2)的
Oracle 11g
OCM
证书获得者。他是危地马拉第一位
OCM
证书获

得者,另外也是最年轻(26
岁,
2016.4)的
Oracle 12c
OCM
证书获得者,是中央

美洲第一位
Oracle 12c
OCM,是最近的
2016
年度编辑选择大奖的获得者(拉斯

维加斯,内华达州)。他经常在
Oracle
全球技术大会上发表演讲,包括
2013



2016
年的
Oracle
技术网络拉丁美洲年会、合作会议(美国)以及
Oracle

OpenWorld
等。
Deiby
也是
Oracle 12cR2 beta
版本在危地马拉的第一位测试者。

Deiby
分别用英文、西班牙文以及葡萄牙文发表过多篇技术文章,这些文章发

表在
Oracle
网站和
DELL’s Toad World
上。另外,在自己的博客上,他也发表

过数百篇技术文章。他曾以杰出专家的身份出现在
2014

11
月份和
12
月份


Oracle
杂志上。同时,
Deiby
也是危地马拉
Oracle
用户组(GOUG)的主席、


拉美
Oracle
用户组社区(LAOUC)的技术支持总监,他还是
OraWorld
团队的共

同发起人。目前,
Deiby
拥有自己的公司
NUVOLA,S.A,为拉美地区的客户提供

Oracle
技术服务。

Arup Nanda

DBA
的身份工作超过
20
年,工作经验几乎涉及
Oracle


术的所有方面,从建模到性能调整,再到
Exadata
均有涉猎。他已经发表过大


500
篇文章,是
5
本书的合著者,发表过
300
多场演讲。其博客网站为
arup.

blogspot.com,他也是新手技术导师,是一名经验丰富的
DBA。他曾于
2003


获得过
Oracle
年度
DBA
大奖,在
2012
年获得过年度企业架构师大奖。他也是

一位
ACE
总监,同时也是
Oak Table
网络的成员。



Mike Donovan

2007
年加入
Dbvisit,在该公司,
Mike
扮演了多个角色,

包括担任全球支持团队的领导人以及数字业务开发先驱。并且就在最近,他成

为该公司的
CTO。
Mike
对新技术有着狂热的激情,他与客户及合作伙伴一起

工作,努力搭建数据库技术与大数据等前沿技术之间的桥梁,从而创造出商业

价值。他喜欢接受挑战,会尝试探求更智能、更低成本的解决方案或替代方案。

Mike
具有技术、艺术以及客户支持和软件开发等多方面的复合背景。他对

Oracle
数据库技术极有热情,并为之工作超过
10
年的时间。他也在多个行业会

议上发表演讲,包括
OOW、
RMOUG、日本数据技术会议以及合作会议等。

Mike
作为产品
DBA
工作多年,获得了从
9i

12c
的多项认证。




Oracle Database 12cR1
版本(12.1)中, 开始引入名为“多租户”的新选项。

从那时起,新的术语“可插拔数据库”便传播开来。但是这个术语,往往意味

着对该特性或其影响并没有清晰的理解。从
12c
的第一个版本开始,多租户已

经是
Oracle
数据库中最为重大的架构变革之一,同时该选项在数据库软件中已

经被落地实施。多租户选项带来了很多新的特性,但也影响到了
Oracle DBA

进行日常管理的方式。从
12c
的第二个版本(12.2)开始,对多租户选项的可用特

性进行了更多的扩展。现在比较清楚的一点就是,旧的系统架构已经被抛弃,

多租户则已经开始生根发芽——不容忽视。

12cR2
中多租户的到来,需要
DBA
调整他们现有的思考方式,以及进行日

常管理的方式。无论是运行单租户数据库,还是运行包含大量租户的数据库,

都需要经历一个新的学习过程。所以,相比于单纯描述多租户这个新东西究竟

包含了什么内容,本书更倾向于描述与
DBA
相关的工作究竟发生了怎样的变

化,无论是核心的日常维护操作,还是一些相关的高级特性。可以将本书视为

Oracle Database 12c
的管理指南。此外,还可以学到关于这些新特性的一些实


战知识,包括语法上的改变,以及最佳实践等方面的内容。本书由三位具有丰


DBA
经验并具备相关认证的
DBA
撰写,并经由诸多技术精湛的审核人员进

行严格审查,从而使内容的价值得到进一步的提升。唯有如此,才能让你带着

洞察一切的激情来了解
Oracle
数据库的管理工作。

本书第Ⅰ部分介绍多租户的功能。其关键问题包括,
Oracle
公司为何要引

入这一选项,并以何种方式来模仿其他数据库产品,以及该选项是否能够真正

为我们设计并部署应用的方式所需要。第
1
章专注这些问题并解释多租户架构。


2
章讨论容器数据库(CDB)的创建流程,以及如何正确完成这一流程。因为


12c
版本中,创建
CDB
已经是默认的选项,不管信不信,我们真的遇到一些

人在对
CDB
毫不知情的情况下就创建了
CDB。在对多租户的各种特性进行详

细描述之前,第
3
章会为你提供信息,让你决定究竟是选择使用
CDB
还是非

CDB
数据库,并且第
3
章还提供不同可用版本和选项的概要信息。

第Ⅱ部分将会讲述当使用多租户特性时,你的日常工作将会发生怎样的改

变。这一部分从第
4
章开始,该章关注
PDB
的创建与管理,并且也会涉及将数

据库升级到
12c
版本的内容。第
5
章将会详细讨论数据库的网络与服务。接下

来的第
6
章,则会关注另一个重要议题——安全——我们将探讨
PDB
的隔离、

用户的公共性以及加密。

第Ⅲ部分将会讨论备份与复制操作等方面的巨大提升。当然,主要是在

PDB
级别。第
7
章将会详细研究作为每一个
DBA
都应该足够熟悉的领域——

备份和恢复——以及如果需要的话,如何将数据库恢复到过去的某个状态。第

8
章讨论如何使用数据库闪回技术实现归档,以及如何在
PDB
级别实现基于时

间点的恢复。本部分的最后一章,第
9
章将会研究如何插入/拔出
PDB,以及如

何对
PDB
进行克隆、传输或在线重定位(online relocation)。

在本书的第Ⅳ部分,你将会在一个新的层次或级别上学习多租户。当对多


PDB
进行集成时,将不得不意识到资源管理器(Resource Manager,
RM)的价

值。关于
RM,将在第
10
章进行讨论。在多租户环境中,
RM
将会发挥极为重

要的作用。第
11
章将会关注如何使用
DG
来对多租户数据库进行保护。第
12

章将会讨论
CDB
中的数据共享问题。与物理克隆或同步技术相比,基于云的

解决方案,则需要数据能够以一种更具灵活性的方式来提供。我们将在第
13

章讨论逻辑复制的相关内容。




1
章 多租户概述
3

1.1
历史课堂:
IT
技术的

新时代4



1.1.1
通往多租户之路


5



1.1.2
方案集成



6



1.1.3
表集成



9



1.1.4
服务器集成



9



1.1.5
虚拟化



10



1.1.6
一个实例管理多个

数据库



10



1.1.7
集成策略总结


11

1.2
系统字典与多租户架构
11



1.2.1
过去:非
CDB


11



1.2.2
多租户容器


14



1.2.3
多租户字典


16



1.2.4
使用容器



21

1.3
什么是
CDB
级别的

集成27


1.4
本章小结
33


2
章 创建数据库
35

2.1
创建容器数据库(CDB) 36



2.1.1 OMF
概述


36



2.1.2 CDB
创建选项



37

2.2
创建可插拔数据库

(PDB) 52



2.2.1
使用
PDB$SEDD
创建

新的
PDB


53



2.2.2
使用本地克隆方式创建

新的
PDB


56



2.2.3
使用
SQL Developer

创建
PDB


57



2.2.4
使用
DBCA
创建
PDB


60



2.2.5
使用
Cloud Control

创建
PDB


61

2.3
使用
catcon.pl
脚本
62

2.4
本章小结
64


3
章 单租户、多租户以及应用

容器65

3.1
多租户架构不是一个

选项
66



3.1.1
抛弃非
CDB


66



3.1.2
不兼容特性



67

3.2
标准版中的单租户68



3.2.1
数据移动



68



3.2.2
安全



69



3.2.3

SE2
集成


69

3.3
企业版中的单租户70



3.3.1
闪回
PDB


71



3.3.2 PDB
的最大数量



71

3.4
使用多租户选项73



3.4.1
应用容器



73



3.4.2
与多租户选项集成



76

3.5
本章小结
77




4
章 日常管理
79

4.1
选择要使用的容器81

4.2
管理
CDB 83



4.2.1
创建数据库


83



4.2.2
启动与关闭数据库



83



4.2.3
删除数据库


84



4.2.4
修改整个
CDB


84



4.2.5
修改根容器


85

4.3
管理
PDB86



4.3.1
创建新的
PDB


86



4.3.2
打开和关闭
PDB


86



4.3.3
查看
PDB
的状态



90



4.3.4
查看
PDB
的操作

历史



90



4.3.5
在多个
PDB
上运行

SQL


90



4.3.6
修改
PDB


91



4.3.7
删除
PDB


93

4.4
打补丁与升级93



4.4.1
升级
CDB


94



4.4.2
插入



103



4.4.3
打补丁



105

4.5
使用
CDB
级别与
PDB
级别

的参数106



4.5.1 CDB SPFILE


106



4.5.2 PDB SFPILE


等价性



106



4.5.3 SCOPE=MEMORY


108



4.5.4 ALTER SYSTEM

RESET


108



4.5.5 ISPDB_MODIFIABLE


108



4.5.6 CONTAINER=ALL


109



4.5.7 DB_UNQIUE_

NAME


110

4.6
本章小结
111


5
章 网络与服务
113

5.1 Oracle Net 114

5.2 Oracle
网络监听
114

5.3 LREG
进程
115

5.4
网络:多线程与

多租户 117

5.5
服务名称
119



5.5.1
默认服务与连接到

PDB


119



5.5.2
创建服务



122

5.6

PDB
创建专用监听
127

5.7
本章小结
130


6
章 安全131

6.1
用户、角色以及权限132



6.1.1
公共用户还是本地

用户?



132



6.1.2
何为用户?



133



6.1.3 CONTAINER=

CURRENT


134



6.1.4 CONTAINER=

COMMON


135



6.1.5
本地授权



138



6.1.6
公共授权



139



6.1.7
冲突解决



140



6.1.8
保持清晰与简单


143



6.1.9 CONTAINER_

DATA


143



6.1.10
角色



145



6.1.11
代理用户


145

6.2
锁定概要文件

(lockdown profile)147



6.2.1
禁用数据库选项


148



6.2.2
禁用
ALYTER

SYSTEM


148



6.2.3
禁用特性



150

6.3 PDB
隔离150



6.3.1 PDB_OS_

CREDENTIALS


150



6.3.2 PATH_PREFIX


151



6.3.3 CREATE_FILE_

DEST


151

6.4
透明数据加密(TDE) 151



6.4.1
创建
TDE


152



6.4.2
带有
TDE
的插入与克隆

操作



157



6.4.3 TDE
总结


157

6.5
本章小结
157




7
章 备份和恢复161

7.1
回到基础知识162



7.1.1
热备份与冷备份


162



7.1.2 RMAN:默认配置



164



7.1.3 RMAN
冗余备份


165



7.1.4 SYSBACKUP
权限


166

7.2 CDB
备份与
PDB
备份
166


7.2.1 CDB
备份



167



7.2.2 PDB
备份


171



7.2.3
别忘了归档日志!



174

7.3
恢复场景
174



7.3.1
实例恢复



175



7.3.2

CDB
进行还原和

恢复


176



7.3.3

PDB
进行还原和

恢复


178

7.4 RMAN
优化方面的一些

考量180

7.5
数据恢复指导183

7.6
块损坏
184

7.7
使用
Cloud Control
进行

备份
184

7.8
本章小结
186


8
章 闪回与基于时间点的

恢复189

8.1 PDB
的基于时间点的

恢复
190



8.1.1
在指定时间恢复

PDB


191



8.1.2 UNDO
在哪里?



193



8.1.3
版本
12.1
中的

PDBPITR
总结



195

8.2
版本
12.2
中的本地

UNDO 196



8.2.1
数据库属性



197



8.2.2
创建数据库



197



8.2.3
修改
UNDO
表空间



198



8.2.4
修改
UNDO
管理

模式


199



8.2.5
共享
UNDO
还是本地

UNDO?



200

8.3
版本
12.2

PDBPITR201



8.3.1
共享
UNDO
模式下的

PDBPITR


201



8.3.2
本地
UNDO
模式下的

PDBPITR


202

8.4
闪回
PDB202



8.4.1
闪回日志



203



8.4.2
使用本地
UNDO
进行

闪回



205



8.4.3
使用共享
UNDO
进行

闪回



205



8.4.4 CDB

PDB
级别的

还原点



206



8.4.5
干净还原点


209

8.5 resetlogs 210

8.6
闪回与
PITR212



8.6.1
何时需要
PITR


闪回?



212



8.6.2
对备库的影响


212



8.6.3
辅助实例的清除


214

8.7
本章小结
215


9
章 移动数据
217

9.1
锚定
PDB
文件位置
218

9.2
插入与拔出
218



9.2.1 PDB
的拔出与插入



219



9.2.2
停留在源库中的已拔出

数据库



220



9.2.3 XML
文件中究竟有

什么?



222



9.2.4
为插入操作检查

兼容性



225



9.2.5
像克隆一样插入


226



9.2.6 PDB
的归档文件



228

9.3
克隆
229



9.3.1
克隆本地
PDB


229



9.3.2
克隆远程
PDB


231

9.4
应用容器的一些考量236

9.5
转换非
CDB
数据库236



9.5.1
插入非
CDB


237



9.5.2
克隆非
CDB


239

9.6

PDB
移动到云上
240

9.7
基于
PDB
操作的

触发器241

9.8
全传输导出/导入241

9.9
可传输表空间244

9.10
本章小




245




10

Oracle
数据库资源

管理器249

10.1
资源管理器基础250



10.1.1
资源管理器关键

术语



251



10.1.2
资源管理器的

需求



253



10.1.3
资源管理器的

级别



253

10.2 CDB
资源计划254



10.2.1
资源分配与使用

限制



254



10.2.2
默认与自动任务

指令



256



10.2.3
创建
CDB
资源

计划



257

10.3 PDB
资源计划265



10.3.1
创建
PDB
资源

计划



266



10.3.2
启用或禁用
PDB
资源

计划



268



10.3.3
移除
PDB
资源

计划



269

10.4
使用初始化参数管理
PDB

的内存和
I/O 269



10.4.1 PDB
的内存分配


269



10.4.2
限制
PDB

I/O


270

10.5
实例囚笼

(instance caging) 270

10.6
监控资源管理器272



10.6.1
查看资源计划与资源

计划指令


272



10.6.2
监控被资源管理器

管理的
PDB


273

10.7
本章小结
274


11

Data Guard 275

11.1 ADG
选项276

11.2
创建物理备库277



11.2.1
使用
RMAN
进行

复制



277



11.2.2
使用
EMCC
创建

备库



289

11.3
在多租户环境下管理

物理备库
292



11.3.1
在源端创建新的

PDB


293



11.3.2

PDB
从源端

删除



294



11.3.3
修改子集



295


11.3.4 EMCC


298

11.4
云上的备库298

11.5
本章小结301


12
章 在
PDB
之间共享

数据303

12.1
数据库链接304

12.2
共享公共只读数据305



12.2.1
可传输表空间


306



12.2.2
存储快照与基于写的复

制(copy on wirte)


307

12.3

PDB
视图308



12.3.1
简单用户表



309



12.3.2
集成数据



313

12.4
跨数据库复制327

12.5
本章小结
327


13
章 逻辑复制329

13.1 Oracle
日志挖掘器

(LogMiner)331

13.2
已过期的特性332



13.2.1 Oracle CDC


332



13.2.2 Oracle
流技术



332



13.2.3 Oracle
高级复制



332

13.3 OGG(Oracle

GoldenGate)333



13.3.1 OGG
中的多租户

支持



333



13.3.2
大数据适配器


343

13.4 Oracle XStream345

13.5
逻辑备库
346

13.6
其他第三方选项347



13.6.1 Dbvisit Replicate


347



13.6.2 Dell SharePlex


347

13.7
本章小结
347


多租户意味着什么


多租户概述




Oracle Database 12c
中,
Oracle
引入了一项发生于数据库体系结构上的

重大调整。在
Oracle Database 12c
以前,一个实例只能打开一个数据库。如果

想处理多个数据库,那么需要启动多个实例才行。因为它们都是完全隔离的架

构,即便这些数据库都安装在同一台服务器上也是如此。这一点与其他关系型

数据库颇为不同,其他很多的数据库,都是可以使用一个实例来管理多个数据

库的。

进入
Oracle Database 12c
之后,一个实例就可以打开多个可插拔数据库,

或者称之为
PDB(Pluggable DataBase)。
Oracle
将之称为新多租户架构,以前旧


的架构名称便被抛弃了。无论是否使用了多租户选项,将来所有的
Oracle
数据

库都会运行在多租户架构上。关于这点事实,所有的
DBA
都是不能忽视的。



1.1
历史课堂:
IT
技术的新时代



在介绍将来的架构之前,让我们先简要回顾一下使用数据库的历史。如你

在图
1-1
中所看到的,我们并不关注时间,而是关注数据库版本,通过它来回


Oracle
数据库的演化历程。




1-1

IT
集成到云




Oracle Database 8i

9i
出现在市场上时, 数据中心使用中型机逐渐变得

流行起来。我们从大型机时代开始步入客户端/服务器时代。而当时的
Oracle

数据库的体系结构,显然是非常适应这一趋势的。由于
Oracle
数据库是使用
C

语言编写的,因此它在多种平台上均能成功运转。并且,所有用户管理信息都

存储在数据库的数据字典中。
Oracle
数据库显然为客户端/服务器架构做好了准

备,它可以使用操作系统来监听
TCP/IP
端口并存储文件。此外,数据库的架构

在小型机上也是可扩展的,这多亏了一个被称为并行服务器的特性。当然,后

来它被称为
RAC(Real Application Cluster)。

随着服务器数量的增长,数据库的数量也随着增长。在那时,一家公司往

往会拥有很多台物理服务器,并且使用
DAS(Direct Attached Disks,直连存储)

作为存储,而在每台服务器上,则又运行着
1
个或
2

Oracle Database8i

9i

实例。

随着数据库数量的增长,管理所有的服务器和磁盘则又成为噩梦一般的存

在。面对着数据的指数级增长,还依然使用内部磁盘来管理这些数据的话,则

容量规划就变得极其困难。此时,
Oracle Database 10g
便应运而生。我们需要


对存储进行集成,这样我们就可以把数据库文件存放到一个存储阵列中,并通


SAN(Storage Area Network, 存储区域网络)让所有的服务器都可以共享访问。

这就是存储集成。

随着时间的流逝,
Oracle Database 11g
开始登场。早期,比较流行的想法

是,我们使用服务器,然后每台服务器上都带有磁盘。但是,相比于设置多台

服务器的容量并对其进行维护而言,虚拟化软件则为我们提供了一种新的可能:

我们可以将多台物理服务器放在一起,并在此基础之上提供虚拟机。在以前的

时代,我们就是使用这样的方法:应用服务器、
SAN

NAS,以及虚拟机。

现在,
Oracle Database 12c
为我们带来一种新的方法。很多拥有集成存储

和服务器的组织,目前已经意识到运营这样的架构其实并非他们的核心业务。

相反,他们将
IT
需求视作一个服务,它应该具有可扩展性和灵活性。小公司想

要使用公有云来提供他们所需的
IT,大一些的公司则打算建立自己的私有云。

在这样的情况下,虚拟化就可以提供
IaaS(Infrastructure as a Service,基础设施

即服务)。但是,我们也需要
AaaS(Application as a Service,应用即服务)和

DBaaS(DataBase as a Service,数据库即服务)。对于
IT
技术生态圈而言,这显

然是一个极为重大的变化。 这与当年从客户端/服务器架构进化到应用服务器时

代颇为相似,无论是扩展性方面还是重要性方面。当然,这一过程并非一蹴而

就——它需要时间。不过,现在就可以断言,在接下来的十年中,混合模型(按

需供应/云)将变得更强大,但是也终将会被云慢慢替代。

正如我们所期待的,新的时代有着不同的需求。数据库的未来也将与集成、

敏捷开发,以及快速就绪等联系在一起。对于
Oracle
而言,类似这样的一些特

性,其实从
9i

11g
一直都处于快速进化之中。比如简单数据传输、克隆,以

及精简指令配置(thin provisioning)等。但是数据库中的两个核心架构功能:一

数据库一实例,以及一数据库一数据字典,一直以来都是如此,尚未做好集成

的准备。为此,
Oracle Database 12c
提供了这两个问题的答案:多租户。在保

留原有可移植性架构的基础之上,
Oracle
对其架构进行了设计调整,从而使得

可以在同一个数据库上运行应用——无论程序是运行在小型服务器上,还是运

行在很大的云上。

1.1.1
通往多租户之路

新的时代是关于集成的时代。一些人会将其想象成一个集中式系统,并辅

以集中管理。但是这带来了新挑战:我们需要越来越高的敏捷性。让一个数

据库快速就绪在今天而言,本非一件容易之事。但至少,我们不能让它变得

更糟糕。

考虑这样一个例子。你是一个
Oracle DBA。然后一个开发人员来到你的办

公桌前,并表示她需要一个新的数据库。在她的意识里,可能会认为这是一个


很简单的需求,你只需要在一个管理界面上单击几下鼠标应该就能搞定。你看

着她,瞪大眼睛,然后告诉她需要去填一张需求申请单,上面需要指定存储、

内存、
CPU
以及可用性方面的内容。并且,你还得解释,这样的需求要上级领

导批准,需要花费数天甚至一周的时间才能建立一个数据库。显然,这里就是

开发人员与运维人员之间通常会产生误解的地方。

开发人员可能以前就没有使用过
Oracle
数据库, 所以她就闪过一些念头,

认为数据库不过就是用来装她的应用程序表的一个容器罢了,并且这个容器

还是一个很轻量级的玩意——在很多其他的非
Oracle
数据库中,这实际上就是

“数据库”。

但是在
Oracle
中,恰恰相反,我们是有一些轻量级的容器——逻辑级别上

的方案(scheme),以及物理级别上的表空间(tablespace)——但是数据库,则不仅

仅是这些内容的整个组合。
Oracle
数据库,是一组方案和表空间的集合,然后

再加上用于管理这些内容的元数据(数据字典),以及为数众多的用于实施各种

特性的
PL/SQL
代码(DBMS
包)。每一个数据库都必须拥有自己的实例,而实

例又由一组后台进程和一块共享内存构成。并且每一个数据库也都有相应的结

构来保护事务的完整性,比如
UNDO
表空间和
REDO
日志。

因此,基于上述这些理由,提供一个新的数据库并不是件很琐碎细微的事

情。要创建一个新的数据库,需要与系统管理员和存储团队进行沟通,因为需

要服务器和磁盘资源。你并不打算在一台服务器上部署太多实例,但是你也不

太可能在一台服务器上只部署一个数据库。正是因为这些,现在我们通常使用

虚拟化技术,然后为每个实例提供一台虚拟机(Virtual Machine,
VM)。当然,

这种方法并不适用于每一个应用或每一个环境,从敏捷的角度来看——因为这

样的话,需要的虚拟机就太多了。另外,当为每一个数据库都不得不分配服务

器、存储以及实例时,最终你就会发现,这样浪费太多资源了。


Oracle Database 12c
以前,这种场景下,对于开发人员来说,比较合适

的方法,就是在现有的数据库中为其创建新的方案。但是这种方法并不总是可

能的,或者说是可行的。让我们解释一下为什么。

1.1.2
方案集成


Oracle Database 12c
以前,方案就是可用的解决方法。每一个应用程序

都可以有自己的方案,或是一组方案,如果想将表和存储过程分开的话。这些

方案在逻辑上是隔离的,并使用权限管理来保证其安全性。

从物理上来讲,也可以为每个应用设置不同的表空间。这就意味着,一旦

数据文件丢失,在还原期间,可能就只有一个应用处于离线状态。如果想将表

空间重新分布到其他文件系统中,也是如此。但是,除此之外,为了优化资源

使用,其他的所有资源我们都是共享的:实例进程与内存、SYSTEM

SYSAUX


表空间、数据字典等。

备份策略和高可用(High Availability,
HA)策略也都是相同的。一个
DBA

管理一个数据库,然后在这个数据库上运行多个应用。在
Oracle
数据库的早期

版本中,数据库就是按照这样的方式来设计的。

1.
可传输表空间


Oracle
数据库中,很多操作都是发生在表空间级别的。尤其是可传输表

空间这一特性。通过这一特性,可以将应用的数据文件物理地拷贝到其他数据

库中,即便是拷贝到一个更高版本的数据库中也是可以的。可传输表空间这一

特性足够重要,因为它被认为是多租户技术的先驱,或者是始祖。1997
年,
Oracle

公司为可传输表空间技术申请专利,名为“数据库系统的可插拔表空间”。而现

在,多租户架构恰恰就是可插拔数据库的基础。

在这里,可插拔的意思,就是可以直接将一个物理结构(数据文件)插到一

个数据库中,并令其成为该数据库的一部分。可传输表空间这一特性,就能够

将用户表空间的数据文件插入到数据库中。 然后就只需要导入相应的元数据(数

据字典实体)即可。这样,在新的数据库中,这些逻辑对象的定义就与数据文件

中的物理内容相匹配了。

当然,在
Oracle Database 12c
中,也可以传输表空间,这样的操作也足够

简单。如果想传输所有的用户表空间,使用“FULL=Y”选项即可。但是相关

的元数据还是需要被逻辑传输。如果有数百张表的元数据需要传输,那么这个

时间可能就会比较长。即便这些表都是空表也是如此。例如,如果想迁移一个

PeopleSoft
数据库,它里面包含
20 000+张表。即便这些表都是空的,导入元数

据也需要几个小时的时间。

正如你将看到的,由于多租户更卓越的性能,传输一个可插拔数据库,实

际上就成为所有数据文件的传输,包括
SYSTEM

SYSAUX
中的数据文件。

显然,这里面就包含了数据字典,甚至还可能包含
UNDO
信息。这就意味着所

有的元数据也将会被物理导入。因此,相比传统的可传输表空间技术,这样的

操作就快了很多。

2.
方案名称冲突

在真实世界中,想实现方案集成,其实还是很有难度的。你可能想将很多

应用都集成到一个数据库中,甚至包括同一个应用的测试环境也想集成进来。

此时,就会面对一系列应用程序的约束问题。

如果应用中的方案所有者是硬编码的,不能修改,那么此时该怎么办?如

果我们需要建立一个电话清单系统,而该系统在数据库中对应的方案为
PB,然

后我们想将多个环境都集成到测试数据库中,那么这显然是被禁止的。原因是

该方案的名称已经硬编码到应用程序以及包中,当然还有其他地方。如果有应


用程序供应商派来的顾问,也许我们还能够比较好地理解这些奇怪的方案名称。

但是如果没有,可能就得去猜测这些方案名称最初究竟是什么意思。

当然,如果应用是在你的掌控之下进行设计的,那么你就可以避免这样的

问题。并且无须多言,你应该在自己的应用程序中从来都不要对方案名称进行

硬编码。可以使用某一用户连接到数据库,然后简单地使用
ALTER SESSION

SET CURRENT_SCHEMA
语句来设置当前应用程序的方案所有者,从而来访

问所有相关的对象。如果有多个方案?那么为应用程序使用多个方案倒也不算

是一个坏主意。

例如,可以使用代码(PL/SQL
包)来分离数据(表)。这能够让数据实现更好

的隔离与封装。但即便是在这种情况下,也不要将表所在的方案名硬编码到包

中。可以在包所在的方案中,为这些对象创建同义词即可。这样,就可以在

PL/SQL
代码中引用这些对象,而不用使用方案名(因为同义词与代码在同一个

方案中),而这些同义词会自动关联到相应的对象上。如果对象名称发生改变,

重新创建同义词就行了。这些动作都可以很简单地完成,也可以自动完成。

3.
公共同义词与数据库链接

对于上面提到的同义词,显然,我们讨论的是私有同义词。不要使用公共

同义词。因为它们会覆盖整个名称空间中的私有同义词。当一个应用程序创建

公共同义词时,无法让其绑定其他任何东西。这就是方案集成的一个限制:不

属于特定方案的对象,容易与其他应用程序,或是其他版本、其他环境中的同

一应用的对象产生冲突。

4.
角色、表空间名称与目录

一个应用程序可以定义或引用其他对象,只要这些对象均处于数据库的公

共名称空间即可——例如角色、目录以及表空间名称。如果一个应用程序在不

同环境中运行,则这些环境其实也可以被集成到同一个数据库中。只需要在执


DDL
脚本时,为不同的环境分别设置不同的参数,从而可以让这些数据库

对象分别适用不同的环境即可。如果不是这种情况的话,那么想实现方案集成

就有难度了。

另外一方面,这些不属于特定方案的对象,也会让数据移动的实现变得更

为复杂。例如,当想使用数据泵(Data Pump)来导入一个方案时,这些对象可能

需要在事先就完成创建。

5.
游标共享

即便一个应用程序是专门为方案集成而设计的,在将所有的东西都集成

到一个数据库里面时,也照样可能会遇到性能方面的问题。我们曾经处理过

一个包含
3000
个方案的数据库,它其实是一堆数据集市(data mart):结构相


同,数据不同。

另外,很显然,应用程序的代码也都是相同的。用户需要连接到其中一个

数据集市,然后执行查询,而这些查询已经在应用程序中进行了定义。这就意

味着同样的查询——甚至在
SQL
文本上也是完全相同的——将会运行在不同

的方案上。如果知道
Oracle
数据库中的游标共享是如何实现的,就立即能够看

到问题所在:一个游标会有上千个子游标。一个父游标会被所有的
SQL
文本共

享,当对象不同时,便会创建不同的子游标。当在多个方案中执行这些代码时,

问题就出来了。
SQL
解析时需要扫描一个相当长的子游标链表,而在扫描期间

需要持有
latch,这显然会导致很严重的库缓存竞争。

在多租户环境下,为满足集成的目的,父游标会被共享,但是在子游标搜

索方面需要进行一些性能方面的提升,从而缓解上述问题。

1.1.3
表集成

当想要对多个环境中的数据进行集成时,而这些环境又有着相同的应用程

序及代码版本,这就意味着要用到的表将会具有完全相同的结构,可以把所

有的东西都放到一张表中。通常情况下,我们是在每一个主键值中添加环境

ID(公司、国家、市场以及其他信息)来区别数据。这样做的好处,是可以一次

性管理所有的东西。例如,当想要添加索引时,可以为所有的环境添加。

基于性能和维护方面的原因考虑,可以基于环境
ID
来对表中的数据进行

物理分区,并将不同的分区数据存放在不同的表空间中。但是,这样做,其隔

离级别就会很低,并进而影响到性能、安全以及系统的可用性。

实际上,大部分应用程序都采用类似这样的设计,并且一般都把数据存储

在一个环境中。绝大部分情况下,添加到主键值前面的
ID
往往都只有一个值,

而这也是
Oracle
引入索引跳跃扫描的原因之一。可以使用虚拟私有数据库策略

来管理对这些环境的访问。可以使用分区交换技术,在物理上实现对这些分区

的独立管理。如果想找一个类似的例子,可以看一下
RMAN
的资料库(恢复目

录):所有已注册的数据库,其信息都存储在相同的表中。但是,在存储不同环

境(测试、开发以及生产环境)中的数据时,或是存储不同版本(数据模型也不尽

相同)的数据时,这样的隔离其实是不够的。

1.1.4
服务器集成

如果有多个独立的数据库,但是又不想为每个数据库都配置一台服务器,那

么可以将这些实例集成到一台服务器上。如果曾经登录过
Oracle

Ask Tom


站(astome.oracle.com/),并咨询过在一台服务器上推荐配置几个实例,
Tom Kate

的答案是这样的:“我们不建议在一台主机上部署多个实例——主机可以是虚拟

机或物理机,我们并不关注——但是你可以这样认为:一台主机
=
一个实例。”


但是在真实生活中,就像我们看到的那样,一台数据库服务器上往往运行着多个

实例。可以在一台主机上安装多个版本的数据库(ORACLE_HOME),也可以在一

台主机上运行多个实例——并且很多时候都是不得不如此。我们曾经见过一台

服务器上运行着多达
70
个实例。

这种情况下,在实例之间进行隔离的方法就比较少了。比如内存,可以通

过设置
SGA_MAX_SIZE
参数来在物理上对内存进行分割。也可以在
Oracle

Database 12c
中使用
PGA_AGGREGATE_LIMIT
来限制进程使用的内存。可以

使用实例囚笼策略,来设置每个实例在
CPU
上运行的最大进程数量。在最新的

Oracle Database 12cR2
中,不需要企业版就可以使用实例囚笼策略。我们将在


3
章中讨论这个主题。

但是,在一台服务器上运行大量的实例依然是个问题。例如,当要重启服

务器时,需要启动大量的进程,并完成内存分配。一次服务器停机,无论是计

划内的还是计划外的,都会对大量应用程序造成影响,并且需要消耗大量资源

来处理多个
SGA
以及数据字典表。

1.1.5
虚拟化

现今,虚拟化是一个非常好的方法,可以在不需要管理大量物理服务器的

前提下实现一个实例一台服务器。可以对环境进行极好的隔离设置,在限制范

围内分配
CPU、内存以及
I/O
带宽。甚至可以使用不同的网络来隔离这些数据

库。但是,即便这些服务器都是虚拟机器,也还是无法解决资源浪费,因为还

是要持有多个
OS、
Oracle
软件、内存以及数据字典。并且,还是得管理多个数

据库——备份恢复、实现高可用特性,比如
Data Guard
等。然后,还是有多个

OS
需要打补丁和监控。

此外,在虚拟化环境中,软件许可也是梦魇般的存在。当进行软件安装

时,
Oracle
软件是按照处理器数量进行授权的,
Oracle
会考虑这些因素,比

如与虚拟化技术相关的授权问题,以及在虚拟机上安装软件并运行,等等。

当然,这些也依赖供应商所提供的管理程序,以及这些管理程序的版本。

1.1.6
一个实例管理多个数据库

那么问题来了,如何找到一种方法,能够实现这样的一种隔离级别:能够

同时满足环境的隔离与资源集成两个目的。显然,这种隔离级别高于方案隔离,

但是又低于我们现在所知道的实例与数据库。也就是说,我们可以在一台服务

器上,使用一个实例来管理多个数据库。


12c
以前的
Oracle
数据库版本中,显然没有这样的功能。但是在现今

的多租户架构中,这种方法就颇为可行了。现在,一个集成的数据库可以管

理多个可插拔数据库。另外,也出现了一种新的隔离级别,即独立数据库——


可插拔数据库,这种架构在环境准备、移动以及系统升级等方面都提供了相

当高的敏捷性。

1.1.7
集成策略总结


1-1
简要总结了在多租户技术出现之前,几种可选的集成策略之间的不

同之处。




1-1
不同集成策略的优劣分析


1.2
系统字典与多租户架构



在多租户架构中,系统字典是变化最大的部分之一。让我们来看看在以前

的版本中,系统字典是如何实现的,以及在
Oracle Database 12c
中,它又发生

了哪些变化。

1.2.1
过去:非
CDB

数据库中既存储数据,又存储元数据。例如,假设在
SCOTT
方案下有一

张表
EMP。该表的描述信息——名称、包含的列以及数据类型等——同样也存

储在数据库中。这些描述信息——也就是元数据——存储于系统表中,并且是

系统字典的一部分。

1.
字典

Codd
的规则(由
E.F.Codd
建立, 其提出了关系模型)定义了关系型数据库中

的元数据必须与数据有着同样的表现形式:可以使用
SQL
来查询元数据或数

据。作为数据库管理员,这样的事情几乎每天都在做。通过查询字典视图,例


DBA_TABLES,来获取数据库中对象的相关信息。
Codd
的规则虽然只用于

表述逻辑层面,并由字典视图提供这些信息;但是
Oracle
走得更远——通过在


关系型表中物理存储这些元数据信息——对于同样类型的表和应用程序表,这

些都为
SYS
方案所拥有,并存储在系统表空间(SYSTEM

SYSAUX)中。

其实,在处理数据及元数据信息存储时,并不需要使用
Oracle
字典的实际

名称和详细信息,如图
1-2
所示。表
SCOTT.DEPT
用于存储用户数据,该表的

定义则存储在字典表中, 即
SYS.COLUMNS。该字典表用于存储列的相关信息,

并且由于这个字典本身也是表,因此它的定义信息也采用同样的方式存储下来。




1-2
数据及元数据信息存储



当然,系统字典表中不仅仅存储了表的定义信息。一直到
8i
版本,数据存

储(表的
extent
信息)的物理描述信息也都是存储在字典表中的。但是,为了适

应可插拔的需求,表空间已经变得越来越自包含了。因此,数据存储的处理方

式,随着本地管理表空间的出现而发生了变化。另一方面,在每一个新的数据

库版本中,都会有很多新的信息会被添加到系统字典中。在当前的数据库版本

中,
Oracle
数据库软件的很大一部分功能,都是用
PL/SQL
包来实现的,而这

些内容,也是存储在系统字典中的。

2. Oracle
管理的对象

对于
Oracle
数据库而言, 其系统字典的实现方式, 就是我们前面所讨论的:

字典存储在数据库中。每一个数据库都有其自己的系统字典。并且当使用逻辑

导入/导出工具(EXP/IMP
或数据泵)来移动数据库时,可能就会发现,有些字典

对象属于系统,有些用户对象属于应用程序,而如何将这些对象区分开来,则


是一件很棘手的事情。当将一个数据库完整地导入(在
IMPDP
中使用
FULL=Y

选项, 这将在第
8
章进行讨论)新建的数据库中时, 你不会想把字典信息也导入,

因为在目标数据库中,这些内容已经存在了。

当然,
SYS
方案中的对象就是字典对象,并且它们会被数据泵忽略。但是

如果有人在
sys
下创建了用户对象,那么这些对象就会丢失,基于
sys
对象的

授权也会丢失。并且在其他地方也可以找到一些系统对象,例如在
OUTLN、

MDSYS
以及
XDB
等方案中。另外,系统中也有很多角色,也可以创建自己的

角色。想把它们区分开也不是那么容易。

幸运的是, 在
12c
版本中,
DBA_OBJECTS、
DBA_USERS
以及
DBA_ROLES

视图中都包含了一个标记,用来指明哪些是数据库维护的对象,是由数据库创建

的,并且不属于你的应用程序。我们可以在
12c
版本中查询出这些
Oracle
维护的

方案列表:




12c
版本中,这显然是一个非常大的提升。可以很简单地确认哪些方案

属于你的应用程序,而哪些又属于数据库系统。
ORACLE_MAINTAINED
标记

列在
DBA_OBJECTS、
DBA_USERS
以及
DBA_ROLES
视图中存在,因此现在

就可以很容易地区分哪些对象是由数据库创建的,以及哪些对象是由应用程序

创建的。

注意:


12c


Oracle


EXP/IMP


EXU8USR


KU_NOEXP_TAB


Data Guard


LOGSTDBY_SKIP_SUPPORT


DEFAULT_PWD$


V$SYSAUX_OCCUPANTS


DBA_REGISTRY


3.
系统元数据与应用程序元数据

我们已经描述了如下元数据结构: 方案、 对象以及角色。 让我们再深入一点,

深入数据去看一看。你已经知道表的定义信息存储在字典表中, 例如在图
1-2
中,

我们简要提了一下
SYS.COLUMN
表。但是,字典数据模型其实是很复杂的。

实际上,对象名称存储在
SYS.OBJ$中,表的信息存储在
SYS.TAB$中,列的

信息则存储在
SYS.COL$中,等等。这些都是表,并且每一个都有自己的定义

信息——元数据——存储在字典表
SYS.TAB$中。例如,它里面存储了你自己

创建的表的信息,但是也存储了所有字典表的相关信息。


SYS.TAB$中,有一行数据是用于存储自身的定义信息。你可能会问,

在创建表时(当然也是创建数据库时),这一行是怎样插入到表中的,因为当时

这张表应该还不存在。在
ORACLE_HOME
中,Oracle
有一段特殊的引导代码(关

于这部分内容,已经超出了本书的范围。不过可以查看
ORACLE_HOME/

rdbms/admin
目录下的
dcore.bsq
文件。也可以查询
BOOTSTRAP$表,看看在启

动阶段,数据库是如何在字典缓冲区中创建这些表的。此时这些基础的元数据

都是立即可用的,从而允许对余下的元数据进行访问)。

所有的元数据都存储在这些表中,但是在非多租户环境下有一个问题:系统

信息(属于数据库的信息)与用户信息(属于应用程序的信息)是混杂在一起的。这

些元数据都存储在同样的表中,并且所有这些东西都存储在同一个容器——数

据库中。

这就是多租户架构中与之前不同的地方:我们现在可以使用多个容器,从

而将系统信息与应用程序信息分离开来。

1.2.2
多租户容器

在多租户数据库中,最重要的结构就是容器。一个容器包含数据和元数据。

多租户中的不同之处在于:一个容器可以包含多个容器,从而分离对象,无论

是物理上还是逻辑上。一个容器数据库可以包含多个可插拔数据库,以及一个

根容器,用来存储公共对象。

多租户数据库是容器数据库(Container DataBase,
CDB)。在原有的架构中,

一个数据库就是一个单一的容器,并且无法再分,这被称为非
CDB。在
12c
版本

中,可以选择是创建
CDB
还是非
CDB。可以创建一个
CDB,也就是多租户数据

库,通过在实例参数中设置
ENABLE_PLUGGABLE=true,并且在
CREATE

DATABASE语句中添加
ENBALE PLUGGABLE
选项来完成(更多细节请参阅第

2
章)。

这样就会创建出一个
CDB, 其中可以包含其他容器。这些容器可使用数字、

容器
ID
或名称进行标识。一个
CDB
中至少包含一个根容器和一个种子容器,

也可以添加自己的容器,在
12.1
版本中,最多可以添加
252
个容器;在
12.2


版本中,则可以多达上千个容器。

1.
可插拔数据库

多租户的目的是集成。相比于在一台服务器上部署多个数据库,现在我们

只需要创建一个集成的数据库即可,也就是
CDB。它里面可以包含多个可插拔

数据库(PDB)。并且每一个
PDB
对于它的用户来说,都是一个完整的数据库。

它有多个方案、公共对象,有系统表空间、字典视图等。

多租户架构可以用来在私有云或公有云上进行集成。可以实现数百个甚至

上千个
PDB
的集成。其目的是,可以提供多个
PDB
的快速就绪服务,但呈现

出来的状态却像是一个数据库。根据这种设计方式,任意连接到一个
PDB
的用

户都无法区分自己是连接到了一个
PDB
还是一个独立的数据库。

另外, 所有以前版本中使用的命令现在照样可用。例如, 当连接到一个
PDB

时,可以执行
shutdown
来关闭这个
PDB。当然,它实际上并不会关闭实例。

因为该实例还管理着其他
PDB。但是对于用户来说,他所看到的,与关闭一台

独立数据库并无二致。

考虑另外一个例子。我们正连接到一个
PDB,并且我们没有自己的
UNDO

表空间,因为该表空间是
CDB
级别的(在
12.2
版本中,我们可以改变这一点,

但是到第
8
章才能看到相关内容)。让我们试着创建一个
UNDO
表空间:



这里并没有报错。但是
UNDO
表空间显然没有创建出来。毕竟,要创建一


100TB
的数据文件是不可能的。我们所提交的语句只是被忽略了。其想法是,

既然在一个数据库中提交的脚本可以创建一个
UNDO
表空间, 那么这样的语法

在一个
PDB
中显然也是应该被接受的。被接受的原因是,所有在非
CDB
中可

以做的事情,在
PDB
中必须也是可以进行的。但是它被忽略了,因为
UNDO

表空间是
CDB
级别的对象。

在多租户环境中,也会有一些新的命令可用,并且你所知道的所有命令也

都被
PDB
所接受。可以为一个
PDB
用户授予
DBA
角色,这样该用户就可以做

一个
DBA
能够做的所有事情。并且该
PDB
用户会被从其他
PDB
中隔离出来,

并将也将无法看到
CDB
级别的信息。


2. CDB$ROOT

你的
SYSTEM
表空间有多大?在数据库刚刚创建时,它差不就有几个
GB

那么大了。对于数据库创建,我们这里并不是指
CREATE DATABASE
语句,而

是指运行
catalog.sql
以及
catproc.sql(当然,在多租户环境中,我们就不这样称呼

它们了,我们称之为
catcdb.sql。实际运行的脚本还是一样)。一个空数据库的字

典表,也将会占用数
GB的空间,用来存储字典结构以及系统包,它们都是
Oracle

软件的一部分——ORACLE_HOME
下的二进制文件——但它们是以存储过程

和包的形式部署在数据库中的。如果在一台服务器上部署
50
个数据库,那么就有

50

SYSTEM
表空间并存储同样的内容(假设它们的版本和补丁号都一样)。如果

想对数百个或数千个数据库进行集成, 正如对
PDB
所做的那样, 你可能不想对每

一个数据库都存储同样的内容。可以将所有的公共数据只存储在一个容器中,

并让其他容器共享这些内容。这就是
CDB$ROOT:它是一个
CDB
中唯一的非

PDB
容器,用来存储
PDB
之间的所有公共信息。

基本上,
CDB$ROOT
将会存储所有的字典表、 字典视图、 系统包(以
dbms_

开头)以及系统用户(SYS、
SYSTEM
等)——并且不再存储其他内容。不要在

CDB$ROOT
中存储用户数据。如果需要,可以在所有的
PDB
中创建自己的用

户。关于公共用户,可以在第
6
章中了解更多信息。

也可将
CDB$ROOT
视为
ORACLE_HOME
的扩展。它是数据库软件的一

部分,并存储于数据库中。它与
ORACLE_HOME
的版本相关,只要版本相同,

那么所有
CDB
中的
CDB$ROOT
都是一样的。
12.2.0.1
版本中的
CDB$ROOT

与你的数据库基本也是一样的。

3. PDB$SEED

多租户数据库
CDB
的目的是创建多个
PDB。不仅如此,还应该能够根据

需要,简单快速地创建
PDB。这也是
DBaaS(DataBase as a Service,数据库即服

务)架构所关注的。如何通过
DBCA
来快速创建一个数据库?可以通过一个包

含所有文件的模板来创建数据库。如果能够克隆一个现成的空数据库,那么就

不再需要去重新创建所有的东西了(正如
catalog.sql

catproc.sql
所做的)。 这就


PDB$SEED: 它是一个空的
PDB, 可以对它进行克隆, 从而创建另外的
PDB。

不能对它进行修改,因为它是只读的,只能将它作为一个新
PDB
的源头。

一个
CDB
最少包含一个
CDB$ROOT
容器和一个
PDB$SEED
容器。不能

对它们进行修改,只能使用它们。只有在对
CDB
进行升级或打补丁时,它们

的结构才会发生变化。

1.2.3
多租户字典

多租户架构的目的之一,就是将系统元数据从应用程序元数据中分离出来。


系统元数据,
PDB
之间所有的公共信息,都存储在
CDB$ROOT
中,称为系统

对象。例如,包的定义,存储在字典表
SOURCE$中,我们可以通过查询

DBA_SOURCE
视图来获取这些内容。在一个非
CDB
中,该表则存储了系统包

和你自己创建的包——有的包由
SYS
拥有,有的则由应用程序方案拥有;就让

我们叫它
ERP
吧。在多租户环境中,
CDB$ROOT
只包含系统元数据,因此在

前面的例子中,这也就意味着这些都是
SYS
包。

在我们指向应用程序的
PDB
中,我们称其为
PDBERP,
SOURCE$中将会

只包含我们应用程序的包,也就是
ERP
的包。让我们看一个例子。我们使用

CDB$ROOT
并统计
SOURCE$中的行数。我们将其与
DBA_OBJECTS
进行关

联,从而显示出哪些是
Oracle
管理的对象(系统对象):



SOURCE$中所有的行都是
Oracle
管理的对象,也就是系统包。

现在我们在
PDB
中看一眼:



CDB$ROOT
中,这与上面查询得到的行数相同。但是在
PDB
中:



这里,我们看到有更多的行数。实际上,我们是从
CDB$ROOT
中看到的

这些行。这里有两个原因。首先,我们说存储在
CDB$ROOT
中的是公共信息,

因此在
PDB
中显然也能够看到这些信息。其次,我们说当一个用户连接到一个

PDB
时,该用户在一个独立的数据库中能看到什么,在一个
PDB
中就也应该

能看到什么。而在一个独立的数据库中,基于
DBA_SOURCE
的查询应该显示

所有的内容,包含系统的以及应用程序的。但是在查询
SOURCE$时则不是这

样。当然你也不希望这样。只有视图记录下了这些信息,并且你会期望去查询

这些视图。

PDB
中的字典视图,提供了
PDB
的信息,以及来自
CDB$ROOT
的信息。

它不是分区,也不是一个数据库链接。我们将在接下来的部分看看
Oracle
是如

何进行处理的。

当连接到
CDB$ROOT
时,
DBA_SOURCE
视图将会只显示容器中的信息。

但是新的以
CDB_开头的视图,则会显示所有容器中的内容,你将在本节后面

1.2.4
节的“5.
容器中的字典视图”部分看到这一点。

因此,从物理上来说,这些字典信息是分离的。每一个容器都存储各自用

户对象的元数据,根容器则存储公共部分——主要是系统元数据。从逻辑上来

说,从这些视图中,我们可以看到所有的信息,因为我们在非
CDB
中就可以

看到,
PDB
显然应该兼容这一点。

2.
元数据链接

Oracle
引入了一种新的方式,来将一个容器中的对象链接到其他容器:元

数据链接。每一个容器都拥有所有的字典对象(存储在
OBJ$中并且可以通过

DBA_OBJECTS
访问到),例如前面的例子中用到的系统包名称。但是更多的对

象定义信息(例如包的代码文本)并非存储在所有的容器中,而是只存储在

CDB$ROOT
中。在
OBJ$中,每一个容器都有一个标识,这可以通过
DBA_

OBJECTS
中的
SHARING
列得到。当需要获取某个对象的定义信息时,该标志


就会告诉
Oracle,这些信息需要切换到
CDB$ROOT
容器去获取。

如下是一些关于这些包中的某个包的信息,所有的容器都包含相同的定义

信息,查询
CDB$ROOT

DBA_OBJECTS:



如下信息则是从
PDB
中查询得到:



可以看到,这些对象都具有相同的名称和类型,并且都定义为
Oracle
管理的,

SHARING
列也都为
METADATA LINK。它们有不同的对象
ID。在对它们进行

链接时,只需要使用名称和内部标签。根据这些内容,我们就可以知道,这些

对象都是系统对象(Oracle
管理的),因此当我们在
PDB
中查询这些对象时,

Oracle
就会知道需要切换到根容器来获取它们的信息。这就是元数据链接的具

体处理行为。字典对象往往都比较大,因此只会存储在
CDB$ROOT
中。但是

它们可以通过字典视图,从而在任意位置都可以访问到。

这与元数据有关。对于应用程序而言,相关的元数据则会存储在对应的

PDB
中。
Oracle
管理的对象则存储在
CDB$ROOT
中。后者是静态信息:它们

只有在对数据库进行升级或打补丁时才会更新。可以看到,这样做的好处,一

是可以降低信息的重复程度,二是能够加快
PDB
升级的速度,因为
PDB
中只

是一些链接罢了。


1-3
显示了字典信息是如何分离的,当然也是对前面图
1-2
的简单扩展。

3.
数据链接(在版本
12.1中称为对象链接)

当然,在字典中不仅仅只有元数据。在
CDB
级别,多租户数据库也会存

储一些数据。这里是一个简单的例子。假设
CDB
需要维护一个容器列表,并

将其存储在系统表
CONTAINER$中然后可以通过字典视图
DBA_PDBS
进行访

问。这些数据可以更新,从而用来存储容器的状态信息。但是,这些数据虽然


只在
CDB
级别才有意义,不过所有的
PDB
都可以访问得到。下面我们就来看

看是如何共享这些信息的。




1-3
系统与用户元数据的分离



先查询
CDB$ROOT:



然后查询
PDB:



可以看到,访问
CONTAINER$的视图,实质上是一个数据链接。这就意味

着,当有会话来执行这些查询时,其实信息是从
CDB$ROOT
获取到的。实际

上,
CONTAINER$表在所有的容器中都存在,但是只有在根容器中是真正存储

数据的,其他都是空的。

1.2.4
使用容器

既然有了这么多的
PDB,那么如何使用它们?可以从识别它们开始。

1.
通过名称和
ID
来识别容器

一个集成的
CDB
中,可以包含多个容器,它们可以通过名称和数字,也

就是
CON_ID
来进行识别。在
12c
版本中,所有用来显示一个实例中包含哪些

对象的
V$视图,都额外添加了一列,用来显示
CON_ID,以便标记对象属于哪

一个容器。
CDB
本身就是一个容器,其容器
ID

CON_ID=0。被标记为

CON_ID=0
的对象,都是
CDB
级别的对象,并且不会关联到其他容器。

例如,如下是我们在根容器中查询
V$DATABASE
后得到的信息:



下面则是在
PDB
中执行查询:



如果在不同的容器中执行上述查询,结果可能也会有所不同。但是无论哪

种情况,所获取到的数据库信息,都只是
CBD
级别的。该视图中包含的信息

来自于控制文件,你将看到这些其实就是公共信息,因此
CON_ID
被设置为


如果是非
CDB,那么对于所有的对象而言,
CON_ID
都为
。但是如果是在一

个多租户架构中,那么大部分对象都属于特定容器。

任一
CDB
环境中,第一个容器都是根容器,名为
CDB$ROOT,并且

CON_ID=1。其他所有的容器都是
PDB。

任一
CDB
中的第一个
PDB,都是种子容器,名为
PDB$SEED。因为它是

CDB
中的第二个容器,所以
CON_ID=2。

CON_ID>2
的容器,就是用户
PDB。在版本
12.1
中,可以创建额外的
252




PDB。在版本
12.2
中,则为
4096

PDB。

2.
容器列表

字典视图
DBA_PDBS列出了所有的
PDB(所有的容器,除了根容器)及其状态:



对于
PDB
而言,当刚刚创建时,其状态为
NEW,并且在第一次将其以读/

写方式打开时,其状态调整为
NORMAL,因为在第一次打开
PDB
时,需要进

行一些相关操作。状态为
UNUSABLE
表明该
PDB
创建失败,并且唯一允许的

操作是将其删除。状态为
UNPLUGGED,则表明该
PDB
将会被传输到其他

CDB,而在源
CDB
上,唯一能做的操作,就是将该
PDB
删除。

在版本
12.1
中,可以看到
NEW
这样的状态,此外还有其他一些状态:NEED

UPGRADE,表明该
PDB
来源于其他版本的数据库;
CONVERTING,表明其

来自于一个非
CDB。当然,还有其他三种状态:
RELOCATING、
REFRESHING

以及
RELOCATED。我们将在第
9
章讨论这些内容。

如下信息是从数据库字典中查到的。我们可以通过实例来列出容器的信息,

这里显示了其打开的状态:



在非
CDB
中,
MOUNTED
状态表明当前控制文件已经被读取,但是数据

文件还没有被实例进程打开。这里查询到的结果与之颇为类似:一个处于关闭

状态的
PDB,其数据文件为未打开状态。
PDB
没有
NOMOUNT
状态,因为控

制文件是公用的。

要注意,无论是
SQL*Plus
还是
SQL Developer,都有一种快捷方式,可以



用来显示当前的
PDB。如果正处于根容器中,还可以显示所有的
PDB:



3.
通过
CON_UID

DBID
来识别容器

可以看到,除了容器的名称,还可以通过
ID

CDB
中的
CON_ID
来识别

容器。但是,当移动
PDB
时,其
CON_ID
将会发生变化。基于这个原因,还需要

一个唯一的标识符
CON_UID。该号码在
PDB
发生移动时也依然可以用来标识

PDB。
CDB$ROOT
是一个容器但不是
PDB,并且它也不会移动,因此其
CON_UID


1。

基于数据库的兼容性考虑,每个容器都有一个
DBID。
CDB

DBID
就是

CDB$ROOT,
PDB

DBID
则为
CON_UID。

另外,每一个容器都还有一个
GUID:一个包含
16
个字节的
RAW
值。它


PDB
创建时生成,并且永远都不会再改变。当使用
OMF(Oracle Managed

Files,
Oracle
管理的文件)时,
GUID
被用于目录结构,并作为
PDB
的唯一标识

符。

所有这些标识符都存储于
V$CONTAINER
中,当然也可以使用这些函数来获

取一个容器的
ID:
CON_NAME_TO_ID、
CON_DBID_TO_ID、
CON_UID_TO_ID

以及
CON_GUID_TO_ID。如果容器不存在,就返回
null
值,如下是一些例子:



4.
连接到容器

前面我们对多租户的分析, 是将其作为突破方案集成限制的一种方法来进行

讨论的。那么问题来了,如何在多个方案之间进行切换?而不是使用方案用户进

行直接连接?这里,可以使用
ALTER SESSION SET CURRENT_SCHEMA。

当然,也可以直接连接到一个
PDB,但是这部分内容我们将在第
5
章进行

讨论。这些内容与服务有关,并且这是从用户或应用程序连接到
PDB
的正确做



法。但是现在,你已经连接到了
CDB,可以使用
ALTER SESSION SET

CONTAINER
命令,从而简单地将会话切换到一个新的容器。

现在,我们已经连接到了
CDB$ROOT:



我们来改变一下当前容器:



现在我们就在
PDB
中了:



事务 如果在一个容器中开启了一个事务,那么将无法在其他容器中开启

另外的事务。



可以离开当前事务,并切换容器:



但是现在无法执行
DML
语句,因为它需要一个新的事务:



首先,需要回到原来的容器并结束事务:



然后可以在另外的容器中开启一个新的事务:



游标 如果在一个容器中打开了一个游标,将无法在另一个容器中对该游

标进行获取操作。需要回到游标所在的容器并进行获取:



基本上,从一个容器切换到另外一个容器往往是很容易的。但是在不同的

容器中进行的操作,则是相互隔离的,并且以前容器中的状态是无法共享的。

例如,我们连接到
PDB1,设置
serveroutput

on,然后使用
dbms_output

命令:



dbms_output
产生了输出,可以看到
USERENV
显示了当前的容器名称。

现在我们切换到
PDB2:



这里就没有任何输出结果了。
serveroutput
只是在
PDB1
中进行了设置,我

们需要在
PDB2
中也进行设置:



现在我们回到
PDB1:



这里就不需要再次设置
serveroutput
了。当我们切换回来时,我们重新获取

了原来
PDB
中的状态。

使用
JDBC

OCI
我们的例子是在
SQL*Plus
中运行的,但是其他客户

端就不能这么做了。当使用一个在根容器中进行定义的用户(公共用户),并且

该用户也被授予
PDB

SET CONTAINER
系统权限时,就可以切换到这个

PDB。可以使用
JDBC(Java DataBase Connectivity )或
OCI(Oracle Call Interface)

来完成这个操作。例如,可以在应用服务器上配置一个连接池,这样在拿到连

接时,就可以将连接切换到所需的容器。当为数据库多租户创建公共应用服务

器时,这种方法是值得考虑的。

注意:


12.2


PDB


12.2


ORA-24964:ALTER SESSION SET CONTAINER


设置容器触发器 基于某些理由,如果想在一个会话进行容器切换时执行某

些动作,例如设置不同的优化器参数,那么可以创建
BEFORE SET CONTAINER


AFTER SET CONTAINER
触发器。

如下是这些触发器的工作机制:



PDB1
中创建
BEFORE SET CONTAINER
触发器, 当处于
PDB1
中,

然后执行
ALTER SESSION SET CONTAINER
时就会触发。如果触发

器读取到了容器的名称,那就是
PDB1。



PDB2
中创建
AFTER SET CONTAINER
触发器,当执行
ALTER

SESSION SET CONTAINER=PDB2
时就会触发。



这就意味着,如果在
PDB1

PDB2
中分别创建
before

after
触发器,那

么当从
PDB1
切换到
PDB2
时,这两个触发器都会分别触发。

这是
PDB
中两种不同的工作方式。也可以通过服务来连接到容器,我们将

在第
5
章讨论这些内容。此时,在会话开始时,就可以使用
AFTER LOGON ON

PLUGGABLE DATABASE
触发器执行某些代码。或者,也可以使用
SET

CONTAINER,然后使用
AFTER SET CONTAINER ON PLUGGABLE DATBASE

触发器。当一个用户在
PDB
中工作时,如果想对这些会话进行某些确定的设置,

那么前面说的这两项操作就都需要进行定义。要注意这里的
PLUGGABLE
单词

并不是必需的,因为这里的语法与数据库的行为是兼容的。

5.
容器中的字典视图

PDB中包含了所有你想从一个数据库中看到的内容。这就意味着对一个PDB

中的字典视图进行查询,其结果应该与对一个数据库进行查询所返回的结果一

致。你同样也拥有
DBA_/ALL_/USER_视图,用来获取
PDB
中对象的元数据。

那些对象,要么有权限去访问,要么是你自己创建的。事实是,系统对象存储在

什么地方是透明的:可以在
DBA_OBJECTS
中看到系统对象,在
DBA_TABLES

中看到系统表,以及在
V$视图中看到实例信息。但是你所看到的行,都跟你当

前所在的
PDB
相关。

当处于
CDB$ROOT
中时,就可以看到
CDB_视图。这些视图就像是所有

打开容器中
DBA_视图的
UNION ALL
结果。 这是一个
CDB
数据库管理员可以

使用的方法,从而查看所有的对象。对于
CDB$ROOT
的用户,
V$视图将会显

示所有容器内的信息。

最后,你可能想知道,你是在非
CDB
环境中还是在多租户环境中。

V$DATABASE
中的
CDB
列为你提供了答案:



1.3
什么是
CDB
级别的集成



对于集成而言,实现共享资源的公共性是其主要目标。在实例与字典之上,

很多数据库结构都是在
CDB
层面进行管理的。我们这里并不讨论数据文件,

因为它们被指定到每一个容器上。并且它们之间唯一的共同之处就是必须拥有

相同的字符集(除了在将一个容器从另外一个
CDB
中传输过来时, 当然这一点我

们要到第
9
章才进行讨论)。在一个容器数据库中,其他类型的文件都是公共的。



SPFILE

对于所有容器而言,数据库实例是公用的,
SPFILE持有该实例的相关参

数,并为整个
CDB
进行属性设置。
SPFILE
包含的设置,无法存储在数据库或控

制文件中,因为这些设置必须在数据库处于
mount
状态之前就可用才行。

有些参数可以在
PDB
级别进行设置(在
V$PARAMETER
中,这些参数的

ISPDB_MODIFIABLE
列为
TRUE)。对这类参数的修改当然也可以持久保存下

来。但是在修改这些参数时,即便在语法上设置
SCOPE=SPFILE,这些
PDB

级别的参数实际也会存储在
CDB
的字典表(即
PDB_SPFILE$)中。它们不会存

储在自身的
PDB
中,因为这些参数必须在打开
PDB
之前就能够访问。在稍后

我们将会看到,当移动一个
PDB(插入/拔出)时,这些参数将会被抽取出来存放

到一个
XML
文件中,并随着
PDB
的数据文件一起被传输。

控制文件

控制文件与数据库中的所有其他结构都有关系。例如,控制文件是唯一真

正存储数据文件名称的地方,在字典表中为
FILE_ID
列,只是对具体位置的引

用而已。在多租户环境中,控制文件位于
CDB
级别,并持有所有
PDB
的数据

文件信息。可以在第
9
章中看到这些与
PDB
相关的内容,即当一个
PDB
被拔

出/插入时,所有与该
PDB
相关的数据文件信息,也会被从控制文件中导出,

然后存储到一个
XML
文件中。

注意:


(control files)


当讨论数据文件时,有一个初始化参数可以用来控制一个实例可以打开的

最大文件数量。就是
DB_FILES,其默认值
200。要注意,如果想创建数百


PDB,那么很快就会达到这一限制。到时候就无法再创建新的表空间或
PDB

了,除非重启实例。在多租户环境中,重启实例意味着会引起很多应用的停机

操作。因此应该避免这一点。故而,当打算在容器中管理多个
PDB
时,不要忘

记对
DB_FILES
参数进行正确设置。

UNDO

在版本
12.1
中,即第一个带有多租户架构的
Oracle
数据库版本中,
UNDO

表空间是公共的,并且处于
CDB
级别。但是在版本
12.2
中,我们有了新的选

项,可以在本地
UNDO
模式下运行
CDB。如果
LOCAL UNDO
被设置为
on,

则每一个
PDB
都拥有自身的
UNDO
表空间, 并且当所有会话往
PDB
的数据块

中写数据时,其
UNDO
信息都会被存储到该
PDB
本地的
UNDO
表空间中。只



有在
CDB$ROOT
中执行的修改操作, 才会将
UNDO
信息记录到
root

UNDO

表空间中。

简单点说,如果可能的话,将
CDB
运行在本地
UNDO
模式下比较好。UNDO

中包含了应用数据,并且如果我们将这些数据存放到公共的
UNDO
文件中的

话,我们就无法实现
PDB
的隔离了。一个需要使用本地
UNDO
模式的原因,

就是当我们打算进行
PDB
的快速闪回或是基于时间点的恢复时。我们将在第
8

章解释这些内容。

临时表空间

临时表空间可以在
CDB

PDB
级别创建。如果某个
PDB
中的用户在运行

会话时没有指定临时表空间,并且该
PDB
也没有默认的临时表空间,该会话将

会使用
CDB
的临时表空间。但这不是推荐的做法。我们可以为
root
的临时表

空间设置限额(MAX_SHARED_TEMP_SIZE),从而控制
PDB
对它的使用。

当需要分配工作区,从而完成对对象链接视图的递归查询时,
CDB$ROOT

的临时表空间一般都由连接到根容器的会话使用, 或者由来自一个
PDB
的会话

使用。

当将一个临时表空间设置为默认的临时表空间时,如果是你创建了该

PDB,那么你也可以指定其他的临时表空间为默认的临时表空间。但是在此之

后,你就无法将
CBD
的临时表空间设置为该
PDB
的默认临时表空间了。

重做日志

重做日志是用来保护实例的,因此,它们也是公共的。重做日志的主要用

途,是对
buffer cache
中所有的修改进行记录,并确保这些所有已提交事务的更

改能够持久保存下去。

多租户环境下的
REDO
数据流与之前版本中的类似,除了在每一条
REDO

记录中都要添加额外的信息用来标记容器之外。并且对于恢复操作而言,
REDO

数据的格式也极为关键,基于此,
Oracle
很少去改变这些东西。

使用统一的
REDO
线程来处理所有的
PDB,对于
DBA
管理
CDB
而言,

也是颇有益处的。在非
CDB
环境中,当打算准备一个新的数据库时,将会花

费很多时间和精力去设置恢复区大小、建立备份,以及创建并配置
Data Guard

物理备库,如果使用了的话。但是在多租户环境下,类似的工作,只需要做一

次就够了,也就是
CDB。因为这就是与数据库可用性相关的功能汇聚的地方:你

的备份、
Data Guard
以及
RAC
配置。可以简单地创建一个新的
PDB,并从这个

已经配置好可用性的环境中受益:它会随着
CDB
进行自动备份,自动在物理

备库中创建(当然这里需要使用
Active Data Guard), 以及能够自动被所有
RAC

实例访问。再强调一次,这就是因为用来实现数据库可用性的关键架构——

REDO
数据流,都是在
CDB
级别进行运作的。



但是,如果只使用一个
REDO
数据流,有时候也会导致性能问题。如果曾

经遇到过与日志写相关的性能问题,例如基于“log file sync”事件的长等待,

那么就可以想象出,当
LGWR
进程需要进行所有
PDB

REDO
写操作时,会

发生什么事情。其结果就是,如果
LGWR
无法跟上
REDO
的生成速度,那么

当用户执行提交操作时,就不得不进入等待状态。

因此,基于
LGWR
的可扩展性考虑,
Oracle

12c
版本中引入了多线程

LGWR
结构。这里,
LGWR
是一个协调进程, 然后有多个从属进程(LG00、
LG01

等)与之相关联。这样,实例的
REDO
数据流就可以采用并行方式进行数据写

操作。当然,
RAC
仍然是另一种实现
REDO
并行处理的方式。需要牢记在脑

海中的是,在多租户环境中,调整
LGWR
以及
REDO
写的数量是至关重要的。

当进行集成时,需要对存放
REDO
日志的磁盘性能加以特别关注。

数据文件

存储在表空间数据块中的数据文件,属于各自的容器,但它们也同样为

CDB
所管理。对于
CDB
而言,这些数据文件都有唯一的标识符,也就是

FILE_ID:



relative file number,中文为相对文件编号,是随着可传输表空间被引入进

来的。因此在
12c
以前的版本中,这个特性已经存在相当一段时间了。多租户

环境下,在
PDB
中,数据文件是通过表空间编号和该文件在表空间中的相对文

件编号(RELATIVE_FNO)进行标识的。此外,当进行文件的移动、克隆或插入


PDB
中时,文件编号的修改都不是必需的。只有绝对文件编号(FILE_ID)会

被重新编号,从而确保其在
CDB
中的唯一性——但是在控制文件和数据文件



头中,这个重新编号的动作,是极其快速的。

CDB
级别的数据与元数据

至此,我们已经解释了与系统对象相关的字典,它们存储在
CDB$ROOT


SYSTEM

SYSAUX
表空间中。它们是公共的,并且可以被
PDB
访问。但

是除了这些基础的数据库对象(由
catalog.sql

catproc.sql
创建)外, 还有更多的

公共信息也都存储在根容器中。

1. APEX

默认情况下,一旦安装了
APEX(在版本
12.2
中,可以选择该组件),它就

处于
CDB
级别。
APEX
与系统字典类似,它们都用来存储元数据,并且不需要

安装在
PDB$SEED
或其他
PDB
中。但是,这种方式有一个非常大的缺点:在

你的
CDB
中,只有一个
APEX
版本。并且当想在该
CDB
中插入一个运行
APEX

5.0
版本的非
CDB
时,将会遇到问题。例如,在
Oracle
云服务中,当前的
CDB

上安装的是
APEX 4.2
版本。

注意:


Mike Dietrich


blogs.oracle.

com/UPGRADE/entry/apex_in_pdb_dose_not


APEX 5.0


Oracle


APEX


PDB


Oracle Application

Express(APEX)


2. AWR

AWR(Automatic Workload Repository,自动工作量资料档案库)从实例的动

态视图中收集大量的信息(统计信息、等待事件等)。在多租户环境下,这些是


CDB
级别完成的。只有一个
job
用来收集所有容器的所有统计信息,并存储


CDB$ROOT
中。这就是对象链接视图——AWR
视图(以
DBA_HIST
开头)

主要的应用案例。它们可以由每一个
PDB
进行查询,但是读取的数据实际上是

存储在根容器中的。

因此,这里有两个重要的结论。其一,如果移动了一个
PDB,那么
AWR

历史数据将不会随之移动;相反,它将仍然保留在原始的
CDB
中。可以使用

原来的数据库读取这些视图,或者在他处将其导出。但是存储在
AWR
中的

CON_ID,应该是生成快照时的容器
ID,因此需要你去检查
CON_DBID,从而

确认某一指定的
PDB。在每一个以
DBA_HIST
开头的视图中,实际上有三个

不同的标识符:

● DBID是
CDB的
DBID,这与非
CDB环境中的一样。该标识符与
SNAP_ID


INSTANCE_NUMBER
一起,可以用来确定唯一的快照。



● CON_ID
是容器
ID,是生成快照时所查询的
V$视图所在的容器
ID。

视图中有些行可能不与任意容器相关联,此时
CON_ID=0。其他行则

记录了某个容器对象的统计信息,因此在生成快照时,就记录下了相

应的
CON_ID。

● CON_DBID
用来唯一标识一个
PDB,它和
DBID
用来唯一标识一个数

据库一样。

对于在
CDB
级别收集统计信息的
AWR
而言,第二个结论是:当在
PDB

级别运行
AWR
报告时,它只会过滤出与你的容器相关的统计信息,并且与查


PDB

V$视图得到的信息一样。但是你仍然需要知道,在同一份
AWR


告中,还是可以看到一些在
CDB
级别收集的统计信息(这些行的
CON_ID=0)。

这就意味着,例如,可以在
AWR
的实例统计信息部分,看到实例所完成的逻

辑读的数量,但是在展示具体的细节(在
SQL
部分或段部分)时,只会显示与你


PDB
相关的信息。让我们看一个例子。

在阅读
AWR
报告的细节之前,我们通常会检查一下大部分被捕获的
SQL

语句,因为如果我们不打算去研究
SQL
语句的细节的话,这样的动作就没有必

要继续了。如下是一份
AWR
报告中的
SQL ordered by Gets
部分:



这里显示捕获了
89%的
SQL
语句,并且我们知道,当我们想去研究高逻辑

读问题时,我们有了所需的细节。如果该比例比较低,那么通常意味着我们生

成的报告,覆盖了一个太大的时间窗口。因此大部分
SQL
语句在
end snapshot

之前都已经由于超时而被移出共享池了。但是,当在一个
PDB
上运行
AWR


告时,也可以看到另外一个原因:



购买地址:



https://item.jd.com/12393662.html

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@byun.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。百云公众号手机网站二维码Copyright Yisu Cloud Ltd. All Rights Reserved. 2018 版权所有广州百云计算有限公司粤ICP备17096448号-1
粤公网安备 44010402001142号增值电信业务经营许可证编号:B1-20181529

相关推荐: Redis多实例及主从复制环境搭建

一、redis主从复制原理 和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 12/31 22:16
下一篇 01/01 14:38