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

内容来源:2017 年 04 月 08 日,ITPUB管理版版主吕海波在“DBGeeK+PG数据库技术沙龙(4月杭州站)”进行《Oracle中最容易被忽略的那些实用特性》演讲分享。

阅读字数:5457 | 14分钟阅读

摘要

本次演讲主要围绕Oracle的几个特性展开,包括多租户、In-Memory Option、多LGWP、逻辑读优化。

嘉宾演讲视频PPT回顾,请复制链接:http://t.cn/RdHo5AI,粘贴至浏览器地址栏即可。

云端数据库:多租户

多租户在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三种状态其中之一。

其实我们可以将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。

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,目前都建议使用这种方式。一种手动创建。

上图是手动创建的步骤,要注意的是标红区域。其中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

// 1、以受限模式打开数据库:
shutdown immediate;
startup restrict mount exclusive;
alter database open read only;

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

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

// 4、执行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中则是多个链表(一般为4、5个)由1个锁保护。

(独占模式)

(共享模式)

Oracle通过CBC Latch来保护链表,要访问链表需要先获得它,然后搜索链表找到某一个BH,最后在BH中获得BA地址。在以前的版本中CBC Latch只有持有和不持有模式,也就是说没有共享的情况,直到最新版本中才有了共享、独占模式。

共享模式主要是通过在BH中添加Fast CR PIN来实现,每多一个人读,引用计数就会加一。

新的机制查询操作时锁开销更低,读与读完全不再阻塞,提高并发,CBC Latch竞争是Select与DML和CR块间的竞争。Select间不会再有CBC Latch竞争。竞争优化的重点是缩短DML执行时间、减少事务持续时间(尽快提交)。

以上为全部分享内容,谢谢大家!

相关推荐 推荐文章

  • 你是否知道怎样借助ES在不同场景下构建数据仓库
  • 基于PG数据库插件的SQL规范审核工具
  • Oracle 数据库一体机的崛起

原文发布于微信公众号 - IT大咖说(itdakashuo)

原文发表时间:2018-07-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏做全栈攻城狮

安卓开发基础教程-Android多界面应用程序开发

本套教程主要讲解安卓开发的相关知识,从基础到精通。一方面可以巩固自己所得,另一方面可以帮助对安卓开发感兴趣的朋友。

1144
来自专栏Golang语言社区

mysql_stmt_prepare failed! error(1461)Can't create more than

1461错误, mysql_stmt_prepare failed! 今天现场咨询我们问如何处理1461错误。 mysql_stmt_prepare faile...

5448
来自专栏猿湿Xoong

Android 8.0 SystemUI(四):二说顶部 StatusBar

大家好,我是ptt,本篇是 SystemUI 的第四篇,也是 StatusBar 的第二说。

7314
来自专栏技术小黑屋

Android内存泄漏检测利器:LeakCanary

到这里你就可以检测到Activity的内容泄露了。其实现原理是设置Application的ActivityLifecycleCallbacks方法监控所有Act...

1212
来自专栏技术小黑屋

Android中实现用户无感知处理后台崩溃

正所谓,要想没有bug,就一行代码也不写。App到了用户的手里,肯定是崩溃越少越好。Android中的崩溃处理和iOS不太一样,iOS崩溃通常是闪退,而安卓会出...

661
来自专栏项勇

笔记89 | Canbus升级程序指南

为方便客户升级,我们定了将升级文件拷至U盘根目录,插到机器USB接口,点击我们的升级程序就可以进行升级

1842
来自专栏Android中高级开发

Android开发之漫漫长途 番外篇——内存泄漏分析与解决

该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索...

742
来自专栏KK的小酒馆

Service的跨进程开发Android开发高级进阶

Service的跨进程通信主要由两种Android提供的方法进行,一个是AIDL,通过创建一个AIDL文件来完成,另一个是利用Messenger,发送Messa...

1182
来自专栏Youngxj

安卓的四大组件之Activity-活动

1715
来自专栏拭心的安卓进阶之路

Android 进阶1:Activity 的生命周期

《Android 开发艺术探索》去年就看完了,但由于当时水平不够,加上自己脑子愚笨,很多知识没有完全消化。还是再来回顾、敲敲、总结一遍吧。 典型情况下的生命周...

21410

扫码关注云+社区