使用脚本创建 12c Container Database

Tags: oracle

如果你很想了解或者打算不依靠 dbca 来创建 CDB(Container Database),那么 "创建脚本" 绝对是完全方式!我习惯于只开启默认模板(通用目的模板)的必选选项来创建数据库,使用所有选项来创建数据库可能会创建存在安全风险的数据库。

最好的方式是通过让 dbca 创建建库脚本来了解 CDB (Container Database) 是如何被创建的。创建过程与普通创建数据库的交互过程一直,只不过通过选择 'generate the script' 复选框来生成脚本而不创建数据库而已。

生成的脚本保存在 $ORACLE_BASE/admin/${ORACLE_SID}/scripts 目录。到这个目录下看看你会惊奇的发现这里有这么多 *.sql 文件:

[oracle@server1 scripts]$ ls -l
total 84
-rw-r-----. 1 oracle oinstall  374 Jul  4 16:05 apex.sql
-rw-r-----. 1 oracle oinstall  970 Jul  4 16:05 context.sql
-rw-r-----. 1 oracle oinstall  534 Jul  4 16:05 CreateClustDBViews.sql
-rw-r-----. 1 oracle oinstall 1805 Jul  4 16:05 CreateDBCatalog.sql
-rw-r-----. 1 oracle oinstall  388 Jul  4 16:05 CreateDBFiles.sql
-rw-r-----. 1 oracle oinstall 1461 Jul  4 16:05 CreateDB.sql
-rwxr-xr-x. 1 oracle oinstall  757 Jul  4 16:05 CUST.sh
-rwxr-xr-x. 1 oracle oinstall 1216 Jul  4 16:05 CUST.sql
-rw-r-----. 1 oracle oinstall  341 Jul  4 16:05 cwmlite.sql
-rw-r-----. 1 oracle oinstall  353 Jul  4 16:05 datavault.sql
-rw-r-----. 1 oracle oinstall 2132 Jul  4 16:05 init.ora
-rw-r-----. 1 oracle oinstall  330 Jul  4 16:05 interMedia.sql
-rw-r-----. 1 oracle oinstall 1127 Jul  4 16:05 JServer.sql
-rw-r-----. 1 oracle oinstall  332 Jul  4 16:05 labelSecurity.sql
-rw-r-----. 1 oracle oinstall 1151 Jul  4 16:05 lockAccount.sql
-rw-r-----. 1 oracle oinstall  348 Jul  4 16:05 ordinst.sql
-rw-r-----. 1 oracle oinstall   91 Jul  4 16:05 PDBCreation.sql
-rw-r-----. 1 oracle oinstall  790 Jul  4 16:05 plug_PDB1.sql
-rw-r-----. 1 oracle oinstall  829 Jul  4 16:05 postDBCreation.sql
-rw-r-----. 1 oracle oinstall  175 Jul  4 16:05 postPDBCreation_PDB1.sql
-rw-r-----. 1 oracle oinstall  323 Jul  4 16:05 spatial.sql
[oracle@server1 scripts]$

虽然在 dbca 创建数据库过程中你没有选择任何选项,不过你可以在这里有选择的执行你需要的脚本。对我来说,我会忽略很多脚本。首先看看主脚本,${ORACLE_SID}.sh

#!/bin/sh

OLD_UMASK=`umask`
umask 0027
mkdir -p /u01/app/oracle/admin/CUST/adump
mkdir -p /u01/app/oracle/admin/CUST/dpdump
mkdir -p /u01/app/oracle/admin/CUST/pfile
mkdir -p /u01/app/oracle/audit
mkdir -p /u01/app/oracle/cfgtoollogs/dbca/CUST
mkdir -p /u01/app/oracle/product/12.1.0.1/dbhome_1/dbs
mkdir -p /u01/fra
mkdir -p /u01/fra/CUST
mkdir -p u01/oradata/CUST
mkdir -p u01/oradata/CUST/pdbseed
umask ${OLD_UMASK}
PERL5LIB=$ORACLE_HOME/rdbms/admin:$PERL5LIB; export PERL5LIB
ORACLE_SID=CUST; export ORACLE_SID
PATH=$ORACLE_HOME/bin:$PATH; export PATH
echo You should Add this entry in the /etc/oratab: CUST:/u01/app/oracle/product/12.1.0/dbhome_1:Y
/u01/app/oracle/product/12.1.0.1/dbhome_1/bin/sqlplus /nolog @/u01/app/oracle/admin/CUST/scripts/CUST.sql

这里除了创建了 PDB seed 数据库目录以外,没什么特别的地方。另外,你注意到这个阿胶本如何配置 PERL5LIB 环境变量了吗?在后面这个变量会很重要!

负责创建数据库的主要脚本是 ${ORACLE_SID}.sql,当然它一直是做这件事情的。这个脚本不会真正创建数据库,它会调用多个脚本来创建不同的组件。这个脚本是一个非常棒的参考文件,可以让我们知道创建数据库需要哪些组件,下面是这个脚本的内容:

set verify off
ACCEPT sysPassword CHAR PROMPT 'Enter new password for SYS: ' HIDE
ACCEPT systemPassword CHAR PROMPT 'Enter new password for SYSTEM: ' HIDE
host /u01/app/oracle/product/12.1.0.1/dbhome_1/bin/orapwd file=/u01/app/oracle/product/12.1.0.1/dbhome_1/dbs/orapwCUST force=y format=12
@/u01/app/oracle/admin/CUST/scripts/CreateDB.sql
@/u01/app/oracle/admin/CUST/scripts/CreateDBFiles.sql
@/u01/app/oracle/admin/CUST/scripts/CreateDBCatalog.sql
@/u01/app/oracle/admin/CUST/scripts/JServer.sql
@/u01/app/oracle/admin/CUST/scripts/context.sql
@/u01/app/oracle/admin/CUST/scripts/ordinst.sql
@/u01/app/oracle/admin/CUST/scripts/interMedia.sql
@/u01/app/oracle/admin/CUST/scripts/cwmlite.sql
@/u01/app/oracle/admin/CUST/scripts/spatial.sql
@/u01/app/oracle/admin/CUST/scripts/labelSecurity.sql
@/u01/app/oracle/admin/CUST/scripts/apex.sql
@/u01/app/oracle/admin/CUST/scripts/datavault.sql
@/u01/app/oracle/admin/CUST/scripts/CreateClustDBViews.sql
@/u01/app/oracle/admin/CUST/scripts/lockAccount.sql
@/u01/app/oracle/admin/CUST/scripts/postDBCreation.sql
@/u01/app/oracle/admin/CUST/scripts/PDBCreation.sql
@/u01/app/oracle/admin/CUST/scripts/plug_PDB1.sql
@/u01/app/oracle/admin/CUST/scripts/postPDBCreation_PDB1.sql

调用 orapwd 命令的那段代码值得一看,它除了强制使用12个字符的密码格式以外没有其他选项。12c 的 orapwd 工具相对于 11.2 版本有了极大的增强,它为不同的目的提供了更多的选项!

[oracle@server1 scripts]$ orapwd
Usage: orapwd file=<fname> entries=<users> force=<y/n> asm=<y/n>
       dbuniquename=<dbname> format=<legacy/12> sysbackup=<y/n> sysdg=<y/n>
       syskm=<y/n> delete=<y/n> input_file=<input-fname>

Usage: orapwd describe file=<fname>

  where
    file - name of password file (required),
    password - password for SYS will be prompted
               if not specified at command line.
               Ignored, if input_file is specified,
    entries - maximum number of distinct DBA (optional),
    force - whether to overwrite existing file (optional),
    asm - indicates that the password to be stored in
          Automatic Storage Management (ASM) disk group
          is an ASM password. (optional).
    dbuniquename - unique database name used to identify database
                   password files residing in ASM diskgroup only.
                   Ignored when asm option is specified (optional),
    format - use format=12 for new 12c features like SYSBACKUP, SYSDG and
             SYSKM support, longer identifiers, etc.
             If not specified, format=12 is default (optional),
    delete - drops a password file. Must specify 'asm',
             'dbuniquename' or 'file'. If 'file' is specified,
             the file must be located on an ASM diskgroup (optional),
    sysbackup - create SYSBACKUP entry (optional and requires the
                12 format). Ignored, if input_file is specified,
    sysdg - create SYSDG entry (optional and requires the 12 format),
            Ignored, if input_file is specified,
    syskm - create SYSKM entry (optional and requires the 12 format),
            Ignored, if input_file is specified,
    input_file - name of input password file, from where old user
                 entries will be migrated (optional),
    describe - describes the properties of specified password file
               (required).

  There must be no spaces around the equal-to (=) character.
[oracle@server1 scripts]$

因为我不喜欢 APEX, InterMedia, Spatia 等等这些特性,因此我删掉了 $ORACLE_SID.sql 中的部分内容。不要删掉 XMLDB 它目前还是有用的。

去掉注释的 init.ora 文件如下所示:

[oracle@server1 scripts]$ grep '^\w' init.ora
db_block_size=8192
open_cursors=300
db_domain=""
db_name="CUST"
control_files=("u01/oradata/CUST/control01.ctl", "/u01/fra/CUST/control02.ctl")
db_recovery_file_dest="/u01/fra"
db_recovery_file_dest_size=4815m
compatible=12.1.0.0.0
diagnostic_dest=/u01/app/oracle
enable_pluggable_database=true
processes=300
sga_target=900m
audit_file_dest="/u01/app/oracle/admin/CUST/adump"
audit_trail=db
remote_login_passwordfile=EXCLUSIVE
dispatchers="(PROTOCOL=TCP) (SERVICE=CUSTXDB)"
pga_aggregate_target=300m
undo_tablespace=UNDOTBS1
[oracle@server1 scripts]$

如果要创建 PDB 你明显需要 12.1 兼容的参数(enable_pluggable_database)。不过幸运的是,其他参数都来自 11.2.

创建数据库

好吧,我不得不承认,前面所有的内容都是真正主题的铺垫,现在进入我们真正的主题:创建数据库和目录!(掌声在哪里!!)

好吧,让我们开始吧:

CREATE DATABASE "CUST"
 MAXINSTANCES 8
 MAXLOGHISTORY 1
 MAXLOGFILES 16
 MAXLOGMEMBERS 3
 MAXDATAFILES 1024
DATAFILE '/u01/oradata/CUST/system01.dbf' SIZE 700M REUSE
  AUTOEXTEND ON NEXT  10240K MAXSIZE UNLIMITED
  EXTENT MANAGEMENT LOCAL
SYSAUX DATAFILE '/u01/oradata/CUST/sysaux01.dbf' SIZE 550M REUSE
  AUTOEXTEND ON NEXT  10240K MAXSIZE UNLIMITED
SMALLFILE DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE '/u01/oradata/CUST/temp01.dbf'
  SIZE 20M REUSE AUTOEXTEND ON NEXT  640K MAXSIZE UNLIMITED
SMALLFILE UNDO TABLESPACE "UNDOTBS1" DATAFILE  '/u01/oradata/CUST/undotbs01.dbf'
  SIZE 200M REUSE AUTOEXTEND ON NEXT  5120K MAXSIZE UNLIMITED
CHARACTER SET AL32UTF8
NATIONAL CHARACTER SET AL16UTF16
LOGFILE
  GROUP 1 ('u01/oradata/CUST/redo01.log') SIZE 50M,
  GROUP 2 ('u01/oradata/CUST/redo02.log') SIZE 50M,
  GROUP 3 ('u01/oradata/CUST/redo03.log') SIZE 50M
USER SYS IDENTIFIED BY "&&sysPassword" USER SYSTEM IDENTIFIED BY "&&systemPassword"
enable pluggable database
seed file_name_convert=(
  '/u01/oradata/CUST/system01.dbf','/u01/oradata/CUST/pdbseed/system01.dbf',
  '/u01/oradata/CUST/sysaux01.dbf','/u01/oradata/CUST/pdbseed/sysaux01.dbf',
  '/u01/oradata/CUST/temp01.dbf','/u01/oradata/CUST/pdbseed/temp01.dbf',
  '/u01/oradata/CUST/undotbs01.dbf','/u01/oradata/CUST/pdbseed/undotbs01.dbf'
);

建库脚本的第一款还是一如既往的标准化,不过从 enable pluggable database 语句开始就是新家伙了。实际上,正是初始化参数中的 enable pluggable database 允许我们创建 CDB,现在你仅需要知道在每个 CDB 创建语句上都需要放置 seed PDB 语句。

CDB 创建完成后,我们需要指定我们存放 PDB 数据文件的位置,如果你使用 Oracle managed Files(OMF,隐含使用 AMS 或者文件系统)完成这个是非常简单的。

脚本dbca 要执行的脚本同样也非常多,下面是主SQL脚本列出的内容:

set verify off
ACCEPT sysPassword CHAR PROMPT 'Enter new password for SYS: ' HIDE
ACCEPT systemPassword CHAR PROMPT 'Enter new password for SYSTEM: ' HIDE
host /u01/app/oracle/product/12.1.0/dbhome_1/bin/orapwd file=/u01/app/oracle/product/12.1.0/dbhome_1/dbs/orapwCUST force=y format=12
@/u01/app/oracle/admin/CUST/scripts/CreateDB.sql
@/u01/app/oracle/admin/CUST/scripts/CreateDBFiles.sql
@/u01/app/oracle/admin/CUST/scripts/CreateDBCatalog.sql
@/u01/app/oracle/admin/CUST/scripts/JServer.sql
@/u01/app/oracle/admin/CUST/scripts/context.sql
@/u01/app/oracle/admin/CUST/scripts/ordinst.sql
@/u01/app/oracle/admin/CUST/scripts/interMedia.sql
@/u01/app/oracle/admin/CUST/scripts/cwmlite.sql
@/u01/app/oracle/admin/CUST/scripts/spatial.sql
@/u01/app/oracle/admin/CUST/scripts/labelSecurity.sql
@/u01/app/oracle/admin/CUST/scripts/apex.sql
@/u01/app/oracle/admin/CUST/scripts/datavault.sql
@/u01/app/oracle/admin/CUST/scripts/CreateClustDBViews.sql
@/u01/app/oracle/admin/CUST/scripts/lockAccount.sql
@/u01/app/oracle/admin/CUST/scripts/postDBCreation.sql
@/u01/app/oracle/admin/CUST/scripts/PDBCreation.sql
@/u01/app/oracle/admin/CUST/scripts/plug_PDB1.sql
@/u01/app/oracle/admin/CUST/scripts/postPDBCreation_PDB1.sql

我个人会将这些文件拷贝到安全的地方并且会删掉一些我不需要的脚本(InterMedia, Apex, Spatial, …)。你可以看到这些脚本非常已于理解,可以拿 CreateDBCatalog.sql 做为示例:

SET VERIFY OFF
connect "SYS"/"&&sysPassword" as SYSDBA
set echo on
spool /u01/app/oracle/admin/CUST/scripts/CreateDBCatalog.log append
alter session set "_oracle_script"=true;
alter pluggable database pdb$seed close;
alter pluggable database pdb$seed open;
host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl -n 1 -l /u01/app/oracle/admin/CUST/scripts -b catalog /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catalog.sql;
host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl -n 1 -l /u01/app/oracle/admin/CUST/scripts -b catblock /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catblock.sql;
host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl -n 1 -l /u01/app/oracle/admin/CUST/scripts -b catproc /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catproc.sql;
host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl -n 1 -l /u01/app/oracle/admin/CUST/scripts -b catoctk /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catoctk.sql;
host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl -n 1 -l /u01/app/oracle/admin/CUST/scripts -b owminst /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/owminst.plb;
host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl -n 1 -l /u01/app/oracle/admin/CUST/scripts -b pupbld -u SYSTEM/&&systemPassword /u01/app/oracle/product/12.1.0/dbhome_1/sqlplus/admin/pupbld.sql;
connect "SYSTEM"/"&&systemPassword"
set echo on
spool /u01/app/oracle/admin/CUST/scripts/sqlPlusHelp.log append
host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl -n 1 -l /u01/app/oracle/admin/CUST/scripts -b hlpbld -u SYSTEM/&&systemPassword -a 1  /u01/app/oracle/product/12.1.0/dbhome_1/sqlplus/admin/help/hlpbld.sql 1helpus.sql;
spool off

你可能会困惑为什么要在主脚本中设置 PERL5LIB 环境变量?这里是回答!这里使用 catcon.pl 来运行脚本而不是在非CDB中运行脚本(?/rdbms/admin/catalog.sql)。

perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl

  Usage: catcon  [-u username[/password]] [-U username[/password]]
                 [-d directory] [-l directory]
                 [{-c|-C} container] [-p degree-of-parallelism]
                 [-e] [-s]
                 [-E { ON | errorlogging-table-other-than-SPERRORLOG } ]
                 [-g]
                 -b log-file-name-base
                 --
                 { sqlplus-script [arguments] | --x<SQL-statement> } ...

   Optional:
     -u username (optional /password; otherwise prompts for password)
        used to connect to the database to run user-supplied scripts or
        SQL statements
        defaults to "/ as sysdba"
     -U username (optional /password; otherwise prompts for password)
        used to connect to the database to perform internal tasks
        defaults to "/ as sysdba"
     -d directory containing the file to be run
     -l directory to use for spool log files
     -c container(s) in which to run sqlplus scripts, i.e. skip all
        Containers not named here; for example,
          -c 'PDB1 PDB2',
     -C container(s) in which NOT to run sqlplus scripts, i.e. skip all
        Containers named here; for example,
          -C 'CDB PDB3'

       NOTE: -c and -C are mutually exclusive

     -p expected number of concurrent invocations of this script on a given
        host

       NOTE: this parameter rarely needs to be specified

     -e sets echo on while running sqlplus scripts
     -s output of running every script will be spooled into a file whose name
        will be
          <log-file-name-base>_<script_name_without_extension>_[<container_name_if_any>].<default_extension>
     -E sets errorlogging on; if ON is specified, default error logging table
        will be used, otherwise, specified error logging table (which must
        have been created in every Container) will be used
     -g turns on production of debugging info while running this script

   Mandatory:
     -b base name (e.g. catcon_test) for log and spool file names

     sqlplus-script - sqlplus script to run OR
     SQL-statement  - a statement to execute

   NOTES:
     - if --x<SQL-statement> is the first non-option string, it needs to be
       preceeded with -- to avoid confusing module parsing options into
       assuming that '-' is an option which that module is not expecting and
       about which it will complain
     - command line parameters to SQL scripts can be introduced using --p
       interactive (or secret) parameters to SQL scripts can be introduced
       using --P

     For example,
       perl catcon.pl ... x.sql '--pJohn' '--PEnter Password for John:' ...

下面是这个脚本的文档:

http://docs.oracle.com/cd/E16655_01/server.121/e17636/cdb_admin.htm#ADMIN14074

但这个脚本很酷,不是吗?所以,我们使用 carcon 来完成目录的安全,下面把命令翻译成人类语言:

host perl /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catcon.pl \
>  -n 1 -l /u01/app/oracle/admin/CUST/scripts -b catalog \
> /u01/app/oracle/product/12.1.0/dbhome_1/rdbms/admin/catalog.sql;

上面命令中,-n 选项貌似没有明确的意义,不过 -l 选项是用来指定日志文件目录,-b 选项指定日志文件的基准名称,然后这个脚本执行 catalog.sql

剩余的脚本遵循相同的逻辑,另一个有意思的脚本是:

host mkdir -p u01/oradata/CUST/PDB1;
CREATE PLUGGABLE DATABASE PDB1 ADMIN USER PDBADMIN IDENTIFIED BY "sys" ROLES=(CONNECT)  file_name_convert=('u01/oradata/CUST/pdbseed',
'u01/oradata/CUST/PDB1');
alter pluggable database PDB1 open;
alter system register;
alter session set container =PDB1;
CREATE SMALLFILE TABLESPACE "USERS" LOGGING  DATAFILE 'u01/oradata/CUST/PDB1/PDB1_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT  1280K MAXSIZE UNLIMITED  EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT  AUTO;
ALTER DATABASE DEFAULT TABLESPACE "USERS";

到这里,你已经使用脚本创建了 CDB 数据库。现在,如果你愿意你可以根据你的需求根据 dbca 生成的模板快速创建 CDB 数据库。注意,dbca 模板是数据库的冷备份并且它从模板克隆数据库肯定比从脚本要快很多。

本文链接:http://www.4byte.cn/learning/109604/shi-yong-jiao-ben-chuang-jian-12c-container-database.html