关于oracle 12c多租户可插拔数据库的启停分析(一)

       在 Oracle Database 12c中多租户架构模式 无疑是所有新特性中最大的卖点,在多租户模式中 把一个单一的多租户容器数据库(CDB:Cantainer Database)挂载很多的可插拔数据库(PDB:P luggable Database )使用,对PDB的不了解,也给日常的工作造成了许多的困扰。

一、关闭PDB时遇到的尴尬     

     在最近接触较多的12c 多租户数据库中,有时在当我在CDB中执行“ alter pluggable database xxx close”关闭 某个pdb时,一直无法停止下,会话也hang住,由于当时还未上线,在对pdb不熟悉的情况下,只能直接在CDB下进行shutdown abort了。

     在多租户的模式下,这实际是不可取的, 整个CDB都shutdown abort 意味着所有的pdb都要同时关闭, 在12.1中多租户 可以包含252个PDB,而12.2里可以包含4096个PDB 。在生产环境中,这是灾难性的措施,而实际上这是源于对pdb的不了解导致。

     以下是在关闭pdb时遇到的过程,通过hanganalyze 我发现停止的过程一直在等待opishd。

      后来我将阻塞的信息提给了SR,而SR认为这与bug有关: Bug 20528052 - Many AQ$_PLSQL_NTFN jobs executed affecting database performance。实际上对12.1版本存在各种bug,我认为见怪不怪。

     而对于PDB的关闭,其实可以不必通过shutdown abort 整个cdb来实现,但在当时我尝试 在pdb 里shutdown abort也貌似停不下来,在12.1.0.1版本数据库是不允许单个pdb shutdown abort 的,而 在12.1.0.2里,引进了一个隐含参数 _enable_pdb_close_abort 来设置允许pdb abort,这个参数默认为false,建议将其设置为true开启,以防关闭pdb时再遇到尴尬。

   在遭遇以上的问题之后,针对pdb的启停追踪分析很有必要, 了解一个新的事物,首先比较好的方式是了解其建立的过程,以下进一步分析PDB的启动过程,来加深认识多租户下的pdb。

二、PDB的启动过程进行分析

首先描述下PDB启动几个主要阶段:

a.pdb以mount状态挂载在数据库实例中

b. PDB_SPFILE$中读取相关参数

c. container$中更新PDB的状态信息

d.通过 创建 bootstrap$引导并加载数据,创建数据库基表。
e.加载其他数据库信息

f.完成启动

1、PDB的初始状态

在oracle CDB open 的状态下,自建pdb默认是以mount状态挂载在数据库中,而 PDB$SEED是种子PDB,以read only状态存在

2、使用10046 追踪启动过程:

通过   10046   事件可以跟踪一下pdb的open过程, 跟踪文件里将记录从  mount  到  open  的过程中,  Oracle  所执行的后台操作。


3、数据库开始解析执行open pdb的语句:

4、从 PDB_SPFILE$中读取相关参数:

而接下来的第二条语句很明显是从obj$表中查询关于PDB_SPFILE$的相关信息:

     而代入3个变量值可以的 PDB_SPFILE$的对象id为179。

     在之后查询的语句都是和 PDB_SPFILE$这个对象有关:

    12c pdb 在启动时便首先读取PDB_SPFILE$ , PDB_SPFILE$  的作用是什么呢?

    实际上在ORACLE 12C中参数文件只是记录了cdb的参数信息,并没有记录任何的pdb的信息,在多租户环境中,每个pdb的参数不一定都相同,因此引入 PDB_SPFILE$来实现pdb参数管理的, p db中参数是记录在root的PDB_SPFILE$基表中,而 整个CDB的工作原理是如果在PDB_SPFILE$中无相关参数记录,则继承cdb的参数文件中值,如果PDB_SPFILE$中有记录则使用该值覆盖cdb参数文件值。

    12c pdb 在启动时便首先遍历PDB_SPFILE$,这也启动一个数据库实例时首先读取参数文件不尽相同。


5、在 container$中更新PDB的状态信息:

接下来对container$表中con_id等于3的记录进行更新。con_id为3对应的是启动的pdb2。

      container$表记录每个pdb的相关信息, 其中obj#=91978 指的是pdb相应对象号,在oracle 12c 多租户中,所建立的每个pdb 实际上也同样以对象的形式存储在CDB中。

除此之外, container$表也记录了pdb的dbid,而每个pdb都有自己的dbid来区别,其中。

      同时从create_scnwrp , create_scnbas , clnscnwrp  clnscnbas  可以看出 container$表 还有记录pdb的SCN相关信息等。


6、在内存中创建 bootstrap$并加载数据进行启动:

接下来便是创建 bootstrap$表, bootstrap$表是pdb启动的引导表。

     在这一步骤中,实际上  Oracle  是在内存中创建  bootstrap$ 的结构, 继续查看  Trace  文件的内容, Oracle  进一步执行的是如下操作:

select line#, sql_text from bootstrap$ where obj# not in (:1 , :2)  

--从 bootstrap$ 递归读取相关的的SQL_TEXT, 由此可以看出是在创建并从数据文件中装载了  bootstrap$ 的内容之后, Oracle  开始递归的从该表中读取信 息,加载数据。

那么  bootstrap$ 中记录的是什么信息呢? 在数据库中, bootstrap$ 是一张实际存在的系统表:

再具体 看一下这张表的内容 :

        从这些语 句中可以看出, bootstrap$  中实际上是记录了一些数据库系统基本对象的创建语句。

而从10046 trace 日志之后的相关语句信息可以看出 Oracle  通 过  bootstrap$ 进行引导,读取相关对象的ddl语句之后进一步创建相关的重要对象,从而启动了数据库。

        bootstrap$ 表在数据库的启动中是非常重要,如果   bootstrap$ 表发生损坏,将影响整个数据库的启动。

以下测试修改 bootstrap$ 表:

仅修改某些数据,貌似并不影响pdb的启动,但如果重启整数据库呢?

重启启动数据库后便因   bootstrap版本不一致而导致open 失败,从而终止了实例, 在这种情况下,最好的方式是从备份中进行不完全恢复。


7、在从   bootstrap$引导初始化之后,便是加载其他数据库信息,包括权限,job,过程,awr相关等,之后便完成了整个pdb的启动。


      从以上pdb的启动整个过程,相对于原来非多租户实例, 其实总体流程与原来区别并不大, 不同之处是在pdb优先读取 PDB_SPFILE$来初始化数据库的参数,之后仍更新pdb的相关状态信息。


三、小结:

    oracle 12c 多租户确实给我们带来极大的便利,但同时伴随的问题也是不少,其中遭遇到的各种bug也是莫名其妙。而从启动过程分析,12c pdb实际也和原来非多租户模式那样差不多,只是在原来的基础上一分为多,其中会添加进了更多的视图来记录pdb相关内容,pdb的启动也需要用 bootstrap$做引导,并且与CDB共用同一份,pdb的参数可以自己独立也可以继承CDB的参数文件等等,而对于pdb探究还在继续,他远不止我们想象的那么简单,但也绝不复杂。 





来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29863023/viewspace-2135231/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29863023/viewspace-2135231/

你可能感兴趣的:(数据库)