1. 程式人生 > >用Oracle12.2手工建立資料庫的一個坑

用Oracle12.2手工建立資料庫的一個坑

作者介紹

楊建榮,DBAplus社群聯合發起人。現就職於搜狐暢遊,Oracle ACE、YEP成員,超7年資料庫開發和運維經驗,擅長電信資料業務、資料庫遷移和效能調優。持Oracle 10G OCP,OCM,MySQL OCP認證,《Oracle DBA工作筆記》作者。

Oracle 12cR2推出以來,確實吸引了不少DBA的注意力,新版本特性還是需要多測試、多演練,做到心中有數,我從12cR2 Linux版本釋出的第一天,就風風火火使用DBCA靜默建庫,嚐了嚐鮮,毫無疑問其中一個亮點就是多租戶,也就是容器資料庫CDB。

12c中因為有了CDB,這個架構相當動了Oracle的地基,所以create database語句也肯定會有大的變化,裡面引入了seed資料庫,而且在12.2中一個較大的變化是undo有local和share模式,這是區別於12.1的一大改進。

大家有沒有試過手工建庫呢?從自己的測試來看是有一些坑的,在此希望給需要的同學一些幫助,少走彎路。當然我在這方面也做了一些功課,我們不光會對12.2中碰到的問題提供解決方法,而且會討論下create database語句在10g、11g中的異同,從多個維度一窺Oracle在這些版本中細小改變,畢竟保持好奇心是一個技術人員求知進步的一把鑰匙。

12c中的create database語句

首先使用create database語句建立資料庫,官方文件在12.2中提示的非常詳細,詳細的步驟可以參考如下連結:

http://docs.oracle.com/database/122/ADMIN/creating-and-configuring-a-cdb.htm#ADMIN13529

對於使用create database語句建立容器資料庫,文件提供了兩類方式,一種是使用OMF(Oracle Managed Files),另外一種是非OMF的方式,對於我們的日常使用來說,其實更傾向於使用非OMF方式,而如果資料庫放在ASM裡,則會傾向自動管理,因為ASM的檔案管理是基於OMF方式的。

為了演示方便,我就使用OMF來說明,這樣create database語句的結構相對清晰簡單。

我們建立一個CDB,建立引數檔案,啟動資料庫至nomount狀態後,就可以使用下面的語句了。

CREATE DATABASE newcdb

USER SYS IDENTIFIED BY sys_password

USER SYSTEM IDENTIFIED BY system_password

EXTENT MANAGEMENT LOCAL

DEFAULT TABLESPACE users

DEFAULT TEMPORARY TABLESPACE temp

UNDO TABLESPACE undotbs1

ENABLE PLUGGABLE DATABASE

   SEED

   SYSTEM DATAFILES SIZE 125M AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED

   SYSAUX DATAFILES SIZE 100M;

和以往的版本不同的就是上面黃色部分標準的部分。

至於PDB seed的意義,就是提供了模板資料,儘可能高效地構建出PDB,可以移步參考之前的一篇文章《Oracle DBCA高階玩法:從模板選擇、指令碼呼叫到多租戶》

12c中的catcdb.sql指令碼

建立資料庫的步驟完成之後,只是完成了不到一半的工作量,另外一部分重點的工作就是初始化資料字典了,我們需要手工執行catalog.sql catproc.sql,這兩個是初始化資料字典的核心指令碼,而其它的一些publd.sql等指令碼則是相應的輔助指令碼,但是12.2卻一改常態,在文件中表示需要使用catcdb.sql 這個指令碼即可。

12.1中的catcdb.sql是一個確確實實的SQL檔案,只是會在指令碼中引用更多的SQL指令碼,無論如何它的本質還是SQL指令碼。

12.2中有了大的改進,catcdb.sql引用的是catcdb.pl這樣一個Perl指令碼,你不會直接看到catalog.sql,catproc.sql這樣的字眼了,這些都被封裝起來了。

當然換湯不換藥,呼叫方式還是類似的。

碰到的第一個問題

這個指令碼個人吐槽一下,執行指令碼需要輸入兩個引數,但是兩個引數的含義也沒給解釋,這一點值得改進,其實需要輸入的是$ORACLE_HOME/rdbms/admin和catcdb.pl兩個引數,如果你不知道輸入什麼也別擔心,因為你會碰到一些其他的問題要先解決,我們不輸入任何引數,先回車。

@?/rdbms/admin/catcdb.sql

SQL> host perl -I &&rdbms_admin &&rdbms_admin_catcdb –logDirectory &&1 –logFilename &&2

Enter value for 1:

Enter value for 2:

Can’t locate Term/ReadKey.pm in @INC (@INC contains: /U01/app/oracle/product/12.2/rdbms/admin /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /U01/app/oracle/product/12.2/rdbms/admin/catcdb.pl line 30.

BEGIN failed–compilation aborted at /U01/app/oracle/product/12.2/rdbms/admin/catcdb.pl line 30.

丟擲的錯誤提示找不到ReadKey.pm,但是我們知道Linux,Unix其實都是自帶Perl的,是不是我們還要單獨去重新配置安裝Perl,其實不必,需要的檔案在$ORACLE_HOME下的Perl目錄,安裝版本是5.22.0了,你只需要把這個目錄引用到PATH變數中就可以了,比如:

export PATH=$ORACLE_HOME/bin:$ORACLE_HOME/OPatch:$ORACLE_HOME/perl/bin: $ORACLE_HOME/jdk/bin:$PATH

第一個問題就解決了,別急,還有幾個問題呢。

碰到的第二個問題

第二個問題來了,那就是找不到util.pm,還是Perl裡的模組。

Can’t locate util.pm in @INC (you may need to install the util module) (@INC contains: /U01/app/oracle/product/12.2/rdbms/admin /home/U01/app/oracle/product/12.2/perl/lib/site_perl/5.22.0/x86_64-linux-thread-multi /home/U01/app/oracle/product/12.2/perl/lib/site_perl/5.22.0 /home/U01/app/oracle/product/12.2/perl/lib/5.22.0/x86_64-linux-thread-multi /home/U01/app/oracle/product/12.2/perl/lib/5.22.0 .) at /U01/app/oracle/product/12.2/rdbms/admin/catcdb.pl line 35.

BEGIN failed–compilation aborted at /U01/app/oracle/product/12.2/rdbms/admin/catcdb.pl line 35.

這個問題該怎麼破,我們只能做點額外的工作了,在Perl的目錄下查詢util.pm竟然沒有,是不是這個地方要重新安裝這個模組,我們換一個思路,把util改為Util,竟然有5條匹配的記錄。

$ find $ORACLE_HOME -name util.pm | wc -l

0

$ find $ORACLE_HOME -name Util.pm | wc -l

5條匹配的記錄內容如下:

$ find $ORACLE_HOME -name Util.pm

/U01/app/oracle/product/12.2/perl/lib/5.22.0/x86_64-linux-thread-multi/List/Util.pm

/U01/app/oracle/product/12.2/perl/lib/5.22.0/x86_64-linux-thread-multi/Scalar/Util.pm

/U01/app/oracle/product/12.2/perl/lib/5.22.0/x86_64-linux-thread-multi/Sub/Util.pm

/U01/app/oracle/product/12.2/perl/lib/5.22.0/x86_64-linux-thread-multi/Hash/Util.pm

/U01/app/oracle/product/12.2/perl/lib/site_perl/5.22.0/HTTP/Headers/Util.pm

這個過程中到底該選哪個目錄下的Util.pm呢,如果多點耐心仔細看看裡面的內容還是能夠找到一些頭緒的,最後選擇的是:

/U01/app/oracle/product/12.2/perl/lib/5.22.0/x86_64-linux-thread-multi/Hash/Util.pm

需要手工修改catcdb.pl指令碼

那麼問題來了,這個catcdb.pl指令碼是不是要改動呢。

修改檔案catcdb.pl,把如下黃色部分的util修改為Util

use Term::ReadKey;              # to not echo password

use Getopt::Long;

use Cwd;

use File::Spec;

use Data::Dumper;

use Util qw(trim, splitToArray);

use catcon qw(catconSqlplus);

再來一輪測試,結果發現還是會有報錯,這種嘗試會讓你開始懷疑自己的選擇到底是不是正確的方向。

如果還是沒有找到,說明在當前的環境變數中沒有匹配到相關的內容,我們需要直接切換到目錄Hash下,然後執行指令碼才可以,這個時候輸出才算有了改觀,提示你輸入密碼。

SQL> host perl -I &&rdbms_admin &&rdbms_admin_catcdb –logDirectory &&1 –logFilename &&2

Enter value for 1: /U01/app/oracle/product/12.2/rdbms/admin

Enter value for 2: /U01/app/oracle/product/12.2/rdbms/admin/catcdb.pl

Enter new password for SYS: xxxx

Enter new password for SYSTEM: xxxx

Enter temporary tablespace name: temp

No options to container mapping specified, no options will be installed in any containers

catcon: ALL catcon-related output will be written to [/U01/app/oracle/product/12.2/rdbms/admin/catalog_catcon_46984.lst]

catcon: See [/U01/app/oracle/product/12.2/rdbms/admin/catalog*.log] files for output generated by scripts

catcon: See [/U01/app/oracle/product/12.2/rdbms/admin/catalog_*.lst] files for spool files, if any

然後就是一段時間的等待,可以從日誌看到會關聯呼叫catalog.sql,catproc.sql等指令碼檔案。

而在處理問題的過程中,也參考了一些資料,發現Deiby Gomez 也碰到了類似的問題,他在部落格裡提供了類似的解決方法。所以說這的的確確是12.2新版本中create database的一個坑,如果你對create database失去了信心,也別擔心,其實不一定是你的錯。

12c的坑討論完了,我們來換個思路,看看10g、11g中是什麼情況。

Create database語句在10g、11g的差別

一個簡單的create database語句在10g、11g還是有一些變化的,這些變化我們需要一些敏銳的“嗅覺”。

Oracle 11g的create database語句大體是這樣的,我們只需要簡單修改下路徑就基本可用。

CREATE DATABASE mynewdb

USER SYS IDENTIFIED BY sys_password USER SYSTEM IDENTIFIED BY system_password

LOGFILE GROUP 1 (‘/u01/logs/my/redo01a.log’,’/u02/logs/my/redo01b.log’) SIZE 100M BLOCKSIZE 512,

GROUP 2 (‘/u01/logs/my/redo02a.log’,’/u02/logs/my/redo02b.log’) SIZE 100M BLOCKSIZE 512,

GROUP 3 (‘/u01/logs/my/redo03a.log’,’/u02/logs/my/redo03b.log’) SIZE 100M BLOCKSIZE 512

MAXLOGFILES 5

MAXLOGMEMBERS 5

MAXLOGHISTORY 1

MAXDATAFILES 100

CHARACTER SET AL32UTF8

NATIONAL CHARACTER SET AL16UTF16

EXTENT MANAGEMENT LOCAL

DATAFILE ‘/u01/app/oracle/oradata/mynewdb/system01.dbf’ SIZE 325M REUSE

SYSAUX DATAFILE ‘/u01/app/oracle/oradata/mynewdb/sysaux01.dbf’ SIZE 325M REUSE

DEFAULT TABLESPACE users

DATAFILE ‘/u01/app/oracle/oradata/mynewdb/users01.dbf’

SIZE 500M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED

DEFAULT TEMPORARY TABLESPACE tempts1

TEMPFILE ‘/u01/app/oracle/oradata/mynewdb/temp01.dbf’

SIZE 20M REUSE

UNDO TABLESPACE undotbs

DATAFILE ‘/u01/app/oracle/oradata/mynewdb/undotbs01.dbf’

SIZE 200M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

而如果你使用11g的create database語句,毫無疑問會在10g環境中丟擲錯誤。

SQL> @createdb.sql

LOGFILE GROUP 1 (‘/u02/oracle/oradata/TEST10G/disk1/redo01a.log’,’/u02/ oracle/oradata/TEST10G/disk2/redo01b.log’) SIZE 100M BLOCKSIZE 512,

*

ERROR at line 4:

ORA-02165: invalid option for CREATE DATABASE

在這一點上,我們需要點耐心,我把10g的建立語句拿出來比較一下,發現有3處不同(標黃部分)。

CREATE DATABASE mynewdb

USER SYS IDENTIFIED BY pz6r58

USER SYSTEM IDENTIFIED BY y1tz5p

LOGFILE GROUP 1 (‘/u01/oracle/oradata/mynewdb/redo01.log’) SIZE 100M,

           GROUP 2 (‘/u01/oracle/oradata/mynewdb/redo02.log’) SIZE 100M,

           GROUP 3 (‘/u01/oracle/oradata/mynewdb/redo03.log’) SIZE 100M

MAXLOGFILES 5

MAXLOGMEMBERS 5

MAXLOGHISTORY 1

MAXDATAFILES 100

MAXINSTANCES 1

CHARACTER SET US7ASCII

NATIONAL CHARACTER SET AL16UTF16

DATAFILE ‘/u01/oracle/oradata/mynewdb/system01.dbf’ SIZE 325M REUSE

EXTENT MANAGEMENT LOCAL

SYSAUX DATAFILE ‘/u01/oracle/oradata/mynewdb/sysaux01.dbf’ SIZE 325M REUSE

DEFAULT TABLESPACE tbs_1

DEFAULT TEMPORARY TABLESPACE tempts1

TEMPFILE ‘/u01/oracle/oradata/mynewdb/temp01.dbf’

SIZE 20M REUSE

UNDO TABLESPACE undotbs

DATAFILE ‘/u01/oracle/oradata/mynewdb/undotbs01.dbf’

SIZE 200M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

(1)第一處不同是關於redo日誌組的設定,10g中預設配置一組日誌中只有一個日誌成員,而在11g中是預設有2個。

(2)第二個不同之處是在10g中有一個配置MAXINSTANCES,而在11g中卻沒有,因為是單例項資料庫,所以不會是這個地方的不同引起的問題。

(3)第三個問題就更加明顯了,在10g中只有default tablespace tbs_1語句而沒有定義明細的資訊,這個語句是不能執行的,還需要手工去補充,在11g中,語句已經補充完整了。只需要簡單的根據自己的需求調整一下即可。

所以第二、三處不同很明顯不是問題的原因,那麼我們看看第一處不同,還有什麼地方有可能會導致語句出現問題。

11g中日誌組的定義的如下:

LOGFILE GROUP 1 (‘/u01/logs/my/redo01a.log’,’/u02/logs/my/redo01b.log’) SIZE 100M BLOCKSIZE 512,

10g中日誌組的定義如下:

LOGFILE GROUP 1 (‘/u01/oracle/oradata/mynewdb/redo01.log’) SIZE 100M,

除了日誌成員的不同外,還有就是blocksize的不同,在10g中沒有blocksize的字樣。

把blocksize去掉,在11g環境中再次執行語句,語句就執行成功了。

原來問題在這裡,因為blocksize的值是在資料庫的原始碼中固定的,與作業系統相關,預設的值為512,在不同的作業系統中會有所不同。

檢視blocksize的配置,可以使用基表。

從Oracle的內部檢視中獲得:

SQL> select max(lebsz) from x$kccle;

MAX(LEBSZ)

———-

512

所以可見在10g和11g的很多細節之處還是可以發現很多值得推敲的地方,Oracle文件也在不斷地改進和完善之中。

小結

以上的問題也算是拋磚引玉,希望大家不要輕視這些技術細節,我們不求每個版本都很完美,但是能夠從中能夠悟出一些更通用的東西,裡面的一點一滴的改進都是我們值得琢磨和推敲的地方,給大家的工作中有所幫助,我的目的也就達到了。

文章來自微信公眾號:DBAplus社群