ไปแก้ไขไฟล์ config ที่ ORACLE_HOME/sqlplus/glogin.sql
--
-- Copyright (c) 1988, 2005, Oracle. All Rights Reserved.
--
-- NAME
-- glogin.sql
--
-- DESCRIPTION
-- SQL*Plus global login "site profile" file
--
-- Add any SQL*Plus commands here that are to be executed when a
-- user starts SQL*Plus, or uses the SQL*Plus CONNECT command.
--
-- USAGE
-- This script is automatically run
--
SET SQLPROMPT "_USER'@'_CONNECT_IDENTIFIER _DATE> " -- Write this
วันเสาร์ที่ 3 มีนาคม พ.ศ. 2561
วันพุธที่ 17 มกราคม พ.ศ. 2561
Create Oracle Active Data Guard step by step
ในการสร้าง Active Data Guard เราต้องมี Physical Standby Database ก่อนแล้วถึง enable Active Data Guard ได้
Preparation:
ตัวอย่างของบทความนี้เซ็ต Primary Database บน Linux ด้วย parameter ตามด้านล่าง
db_unique_name='linux_un'
db_name='orcl'
เซ็ต Standby Database บน Windows ด้วย parameter ตามด้านล่าง
db_unique_name='windows_un'
db_name='orcl'
1. Install Oracle Database software ที่เครื่อง Standby (ต้องเป็น Version เดียวกันและ EE)
2. Primary Database ต้องเป็น archive log mode
3. Primary Database เป็น force logging mode (SQL> alter database force logging;)
4. สร้าง standby redo log ที่ Primary Database ให้จำนวน size เท่ากับ online redo log และมี group มากกว่า 1 group ถ้าเป็น RAC ก็สร้างเพิ่มอีกเป็น n+1 สำหรับแต่ละ thread
Implementation:
1. เนื่องจากเครื่อง Standby เป็น Windows จึงต้องสร้าง Windows service
oradim -NEW -SID windows -STARTMODE manual -PFILE C:\app\KITTI-SRS\product\11.2.0\dbhome_1\database\init.ora
2. ตัวอย่าง Initialization parameters ของทั้ง Primary และ Standby จะมีที่สำคัญคือ
LOCAL_LISTENER , FAL_SERVER , LOG_ARCHIVE_DEST_1 , LOG_ARCHIVE_DEST_2 , DB_UNIQUE_NAME , INSTANCE_NAME , STANDBY_FILE_MANAGEMENT , DB_FILE_NAME_CONVERT , LOG_FILE_NAME_CONVERT)
Primary Database
*.audit_file_dest='/u01/app/oracle/admin/orcl/adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='/u01/app/oracle/oradata/orcl/control01.ctl','/u01/app/oracle/fast_recovery_area/orcl/control02.ctl'
*.db_block_size=8192
*.db_unique_name='linux_un'
*.db_domain=''
*.db_name='orcl'
*.instance_name='linux'
*.local_listener='LISTENER'
*.fal_server='windows' # for switchover purpose
*.log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES)'
*.log_archive_dest_2='SERVICE=windows LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=windows_un'
*.log_archive_config='DG_CONFIG=(linux_un,windows_un)'
*.log_archive_max_processes=8
*.db_file_name_convert='C:\app\KITTI-SRS\oradata\orcl','/u01/app/oracle/oradata/orcl' # for switchover purpose
*.log_file_name_convert='C:\app\KITTI-SRS\oradata\orcl','/u01/app/oracle/oradata/orcl' # for switchover purpose
*.standby_file_management='AUTO' # for switchover purpose
*.db_recovery_file_dest='/u01/app/oracle/fast_recovery_area'
*.db_recovery_file_dest_size=4385144832
*.diagnostic_dest='/u01/app/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=orclXDB)'
*.log_archive_format='%t_%s_%r.dbf'
*.memory_target=1153433600
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'
Standby Database
*.audit_file_dest='C:\app\KITTI-SRS\admin\orcl\adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='C:\app\KITTI-SRS\oradata\orcl\control01.ctl','C:\app\KITTI-SRS\fast_recovery_area\orcl\control02.ctl'
*.db_block_size=8192
*.db_unique_name='windows_un'
*.db_domain=''
*.db_name='orcl'
*.instance_name='windows'
*.fal_server='linux' # for switchover purpose
local_listener='LISTENER'
*.log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES)'
*.log_archive_dest_2='SERVICE=linux LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=linux_un' # for switchover purpose
*.log_archive_config='DG_CONFIG=(linux_un,windows_un)'
*.log_archive_max_processes=8
*.log_file_name_convert='/u01/app/oracle/oradata/orcl','C:\app\KITTI-SRS\oradata\orcl' # for switchover purpose
*.db_file_name_convert='/u01/app/oracle/oradata/orcl','C:\app\KITTI-SRS\oradata\orcl' # for switchover purpose
*.standby_file_management='AUTO'
*.db_recovery_file_dest='C:\app\KITTI-SRS\fast_recovery_area'
*.db_recovery_file_dest_size=4385144832
*.diagnostic_dest='C:\app\KITTI-SRS'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=orclXDB)'
*.log_archive_format='%t_%s_%r.dbf'
*.memory_target=1153433600
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'
Note. db_file_name_convert กับ log_file_name_convert เป็น static parameter ซึ่งต้อง restart database
3. ตั้งค่า Listener เพื่อ enable static service registration เพื่อใช้ในการทำ RMAN duplicate database แบบ active
Primary
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = kittisource)(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0.4/dbhome_1)
(PROGRAM = extproc))
(SID_DESC =
(GLOBAL_DBNAME = linux_un)
(SID_NAME = linux)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0.4/dbhome_1)))
ADR_BASE_LISTENER = /u01/app/oracle
Standby
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = KITTISRS)(PORT = 1521))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = CLRExtProc)
(ORACLE_HOME = C:\app\KITTI-SRS\product\11.2.0\dbhome_1)
(PROGRAM = extproc)
(ENVS = "EXTPROC_DLLS=ONLY:C:\app\KITTI-SRS\product\11.2.0\dbhome_1\bin\oraclr11.dll")
)
(SID_DESC =
(GLOBAL_DBNAME = windows_un)
(SID_NAME = windows)
(ORACLE_HOME = C:\app\KITTI-SRS\product\11.2.0\dbhome_1)))
ADR_BASE_LISTENER = C:\app\KITTI-SRS
4. เพิ่ม TNS alias ใน tnsnames.ora เพื่อให้ Primary กับ Standby สามารถ connect ผ่าน TNS alias ได้
(เพิ่ม alias ให้ LISTENER ด้วยเพราะใช้ใน LOCAL_LISTENER parameter)
Primary and Standby
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = KITTISRS)(PORT = 1521))
)
)
linux =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = kittisource)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = linux_un)))
windows =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = KITTISRS)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = windows_un)))
5. ทำการ copy password file จาก Primary ไปที่ Standby แล้วเปลี่ยนชื่อเป็น pwd<sid>.ora
6. เปิด Standby Database เป็น nomount mode และ start listener (ใช้ parameter file ที่เตรียมไว้และควรสร้างและใช้ spfile แทน)
7. เช็คสถานะของ Primary Database (ต้องเป็น open หรือ mount เพื่อทำ RMAN active duplicate)
8. ใช้ RMAN (ที่เครื่อง Primary หรือ Standby ก็ได้) เพื่อ connect ทั้ง Primary และ Standby
9. ใช้คำสั่ง RMAN duplicate เพื่อทำการคัดลอกไฟล์จาก Primary Database เพื่อไปสร้าง Standby Database
Verification:
1. Query จากเครื่อง Standby Database เพื่อตรวจสอบข้อมูลของ DB
2. เช็ค data files
3. เช็ค online redo log files กับ standby redo log files
4. ตรวจสอบว่า redo transport service ทำงานอยู่ไหม (RFS processes running)
Start and Test Active Data Guard:
1. Open database และเปิด Real-time apply
2. ทดลองสร้าง table และ query
Preparation:
ตัวอย่างของบทความนี้เซ็ต Primary Database บน Linux ด้วย parameter ตามด้านล่าง
db_unique_name='linux_un'
db_name='orcl'
เซ็ต Standby Database บน Windows ด้วย parameter ตามด้านล่าง
db_unique_name='windows_un'
db_name='orcl'
1. Install Oracle Database software ที่เครื่อง Standby (ต้องเป็น Version เดียวกันและ EE)
2. Primary Database ต้องเป็น archive log mode
3. Primary Database เป็น force logging mode (SQL> alter database force logging;)
4. สร้าง standby redo log ที่ Primary Database ให้จำนวน size เท่ากับ online redo log และมี group มากกว่า 1 group ถ้าเป็น RAC ก็สร้างเพิ่มอีกเป็น n+1 สำหรับแต่ละ thread
Implementation:
1. เนื่องจากเครื่อง Standby เป็น Windows จึงต้องสร้าง Windows service
oradim -NEW -SID windows -STARTMODE manual -PFILE C:\app\KITTI-SRS\product\11.2.0\dbhome_1\database\init.ora
2. ตัวอย่าง Initialization parameters ของทั้ง Primary และ Standby จะมีที่สำคัญคือ
LOCAL_LISTENER , FAL_SERVER , LOG_ARCHIVE_DEST_1 , LOG_ARCHIVE_DEST_2 , DB_UNIQUE_NAME , INSTANCE_NAME , STANDBY_FILE_MANAGEMENT , DB_FILE_NAME_CONVERT , LOG_FILE_NAME_CONVERT)
Primary Database
*.audit_file_dest='/u01/app/oracle/admin/orcl/adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='/u01/app/oracle/oradata/orcl/control01.ctl','/u01/app/oracle/fast_recovery_area/orcl/control02.ctl'
*.db_block_size=8192
*.db_unique_name='linux_un'
*.db_domain=''
*.db_name='orcl'
*.instance_name='linux'
*.local_listener='LISTENER'
*.fal_server='windows' # for switchover purpose
*.log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES)'
*.log_archive_dest_2='SERVICE=windows LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=windows_un'
*.log_archive_config='DG_CONFIG=(linux_un,windows_un)'
*.log_archive_max_processes=8
*.db_file_name_convert='C:\app\KITTI-SRS\oradata\orcl','/u01/app/oracle/oradata/orcl' # for switchover purpose
*.log_file_name_convert='C:\app\KITTI-SRS\oradata\orcl','/u01/app/oracle/oradata/orcl' # for switchover purpose
*.standby_file_management='AUTO' # for switchover purpose
*.db_recovery_file_dest='/u01/app/oracle/fast_recovery_area'
*.db_recovery_file_dest_size=4385144832
*.diagnostic_dest='/u01/app/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=orclXDB)'
*.log_archive_format='%t_%s_%r.dbf'
*.memory_target=1153433600
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'
Standby Database
*.audit_file_dest='C:\app\KITTI-SRS\admin\orcl\adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='C:\app\KITTI-SRS\oradata\orcl\control01.ctl','C:\app\KITTI-SRS\fast_recovery_area\orcl\control02.ctl'
*.db_block_size=8192
*.db_unique_name='windows_un'
*.db_domain=''
*.db_name='orcl'
*.instance_name='windows'
*.fal_server='linux' # for switchover purpose
local_listener='LISTENER'
*.log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES,ALL_ROLES)'
*.log_archive_dest_2='SERVICE=linux LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=linux_un' # for switchover purpose
*.log_archive_config='DG_CONFIG=(linux_un,windows_un)'
*.log_archive_max_processes=8
*.log_file_name_convert='/u01/app/oracle/oradata/orcl','C:\app\KITTI-SRS\oradata\orcl' # for switchover purpose
*.db_file_name_convert='/u01/app/oracle/oradata/orcl','C:\app\KITTI-SRS\oradata\orcl' # for switchover purpose
*.standby_file_management='AUTO'
*.db_recovery_file_dest='C:\app\KITTI-SRS\fast_recovery_area'
*.db_recovery_file_dest_size=4385144832
*.diagnostic_dest='C:\app\KITTI-SRS'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=orclXDB)'
*.log_archive_format='%t_%s_%r.dbf'
*.memory_target=1153433600
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'
Note. db_file_name_convert กับ log_file_name_convert เป็น static parameter ซึ่งต้อง restart database
3. ตั้งค่า Listener เพื่อ enable static service registration เพื่อใช้ในการทำ RMAN duplicate database แบบ active
Primary
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = kittisource)(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0.4/dbhome_1)
(PROGRAM = extproc))
(SID_DESC =
(GLOBAL_DBNAME = linux_un)
(SID_NAME = linux)
(ORACLE_HOME = /u01/app/oracle/product/11.2.0.4/dbhome_1)))
ADR_BASE_LISTENER = /u01/app/oracle
Standby
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = KITTISRS)(PORT = 1521))
)
)
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = CLRExtProc)
(ORACLE_HOME = C:\app\KITTI-SRS\product\11.2.0\dbhome_1)
(PROGRAM = extproc)
(ENVS = "EXTPROC_DLLS=ONLY:C:\app\KITTI-SRS\product\11.2.0\dbhome_1\bin\oraclr11.dll")
)
(SID_DESC =
(GLOBAL_DBNAME = windows_un)
(SID_NAME = windows)
(ORACLE_HOME = C:\app\KITTI-SRS\product\11.2.0\dbhome_1)))
ADR_BASE_LISTENER = C:\app\KITTI-SRS
4. เพิ่ม TNS alias ใน tnsnames.ora เพื่อให้ Primary กับ Standby สามารถ connect ผ่าน TNS alias ได้
(เพิ่ม alias ให้ LISTENER ด้วยเพราะใช้ใน LOCAL_LISTENER parameter)
Primary and Standby
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = KITTISRS)(PORT = 1521))
)
)
linux =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = kittisource)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = linux_un)))
windows =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = KITTISRS)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = windows_un)))
5. ทำการ copy password file จาก Primary ไปที่ Standby แล้วเปลี่ยนชื่อเป็น pwd<sid>.ora
6. เปิด Standby Database เป็น nomount mode และ start listener (ใช้ parameter file ที่เตรียมไว้และควรสร้างและใช้ spfile แทน)
7. เช็คสถานะของ Primary Database (ต้องเป็น open หรือ mount เพื่อทำ RMAN active duplicate)
9. ใช้คำสั่ง RMAN duplicate เพื่อทำการคัดลอกไฟล์จาก Primary Database เพื่อไปสร้าง Standby Database
Verification:
1. Query จากเครื่อง Standby Database เพื่อตรวจสอบข้อมูลของ DB
2. เช็ค data files
4. ตรวจสอบว่า redo transport service ทำงานอยู่ไหม (RFS processes running)
Start and Test Active Data Guard:
1. Open database และเปิด Real-time apply
2. ทดลองสร้าง table และ query
วันอังคารที่ 31 ตุลาคม พ.ศ. 2560
Install Oracle Database on Docker Container
Software ที่ใช้คือ Oracle Database 12cR2 (12.2.0.1) บน Oracle
Linux 7 และ Docker Image ที่มี default database ใน multi-tenant
configuration with a single pluggable database
ตรวจเช็ค OS kernel และ ติดตั้ง Docker
Disable SELinux
Enable the
ol7_addons และ ol7_UEKR4 เพื่อโหลด docker จาก yum repository
นี้
#vi /etc/yum.repos.d/public-yum-ol7.repo
ติดตั้ง docker-engine และตรวจสอบ version
# yum install docker-engine
Prepare for install Oracle Database
ติดตั้ง oracle-database-server-12cR2-preinstall package เพื่อเซ็ตอัพ environment ที่จำเป็นและ required package ต่างๆ
เพิ่มพื้นที่ storage ให้กับ docker
container เป็น 30GB (จากเดิม 25GB)
#vi
/etc/sysconfig/docker-storage
อนุญาตให้ oracle user สามารถใช้
sudo และรัน docker commands ต้องเพิ่ม oracle
user ไปที่ /etc/sudoers file.
หรือรัน visudo
#visudo
Switch user ไปเป็น oracle (su – oracle) และ
download Oracle image files และ database zip file
[oracle@kitti-srs ~]$ wget
https://github.com/oracle/docker-images/archive/master.zip
[oracle@kitti-srs ~]$ unzip master.zip
[oracle@kitti-srs ~]$ cd
docker-images-master/OracleDatabase/dockerfiles/12.2.0.1/
Copy oracle 12cR2 database software ไปที่พาธ docker-images-master/OracleDatabase/dockerfiles/12.2.0.1/
สร้าง Docker image
ไปที่พาธ docker-images-master/OracleDatabase/dockerfiles
ตอนนี้พร้อมที่จะสร้าง Oracle Database ใน Docker
Container แล้ว
สร้าง container ด้วยคำสั่ง
$ sudo docker run -p 1521:1521 –name kitti-container
oracle/database:12.2.0.1-ee
ทดลอง Start , Stop , and List Docker Container
$ sudo docker stop kitti-container
$ sudo docker start kitti-container
$ sudo docker ps
Starting an Active Terminal and connect to SQL * Plus
$ sudo docker exec -it <container_name> bash
วันจันทร์ที่ 24 สิงหาคม พ.ศ. 2558
How to change public ip , vip , scan
เปลี่ยน Public IP ก่อน
1. ปิด database และ nodeapps
srvctl stop database -d dbname
srvctl stop nodeapps -n node1
srvctl stop nodeapps -n node2
2. เปลี่ยน Public Interface
oifcfg getif
eth0 192.168.16.0 global cluster_interconnect,asm
eth1 172.16.4.0 global public
oifcfg delif -global eth1
oifcfg setif -global eth1/172.16.21.0:public
เช็คอีกที
oifcfg getif
eth0 192.168.16.0 global cluster_interconnect,asm
eth1 172.16.21.0 global public
* แก้อีก node นึงด้วย
3. แก้ไข VIP Interface
srvctl modify nodeapps -n node1 -A 172.16.21.107/255.255.255.0/eth1
srvctl modify nodeapps -n node2 -A 172.16.21.108/255.255.255.0/eth1
* ถ้าแก้ไม่ได้ให้แก้ network ก่อนเพราะอาจใช้ subnet คนละวง
4. Stop CRS ทั้ง 2 nodes
crsctl stop crs
5. แก้ไข IP Address ที่ OS (/etc/hosts ด้วยก็ได้)
vi /etc/sysconfig/network-scripts/ifcfg-eth1
vi /etc/sysconfig/network-scripts/ifcfg-eth1
6. Reboot all nodes
7. หลังจาก reboot แล้ว database ควรจะ start ขึ้นมาได้ปกติ เราสามารถใช้คำสั่งเช็คได้เช่น
crsctl stat res -t
srvctl status database -d dbname
srvctl status listener
8. แก้ไข scan
srvctl stop scan
srvctl stop scan_listener
srvctl modify scan
srvctl start scan
srvctl start scan_listener
* มันจะปรับค่าให้โดยอ่านจาก VIP ให้เอง
เราสามารถเช็คค่าใหม่ได้ด้วย
srvctl config scan
วันอังคารที่ 11 สิงหาคม พ.ศ. 2558
วิธีสร้าง TAF session failover แบบ SELECT โดยใช้ server side service
สมมุติว่าเราพึ่งสร้าง RAC database ขึ้นมาใหม่และเราอยากให้ขณะ SELECT อยู่แล้วหาก Current instance หลุดไป Session ของเราจะไป SELECT ต่อที่อีก Instance นึงเราต้องสร้าง Service ขึ้นมาเป็นแบบ SELECT type
ตัวอย่าง
1. สร้าง service ขึ้นมา 1 ตัวชื่อ TAF เป็นแบบ SELECT type
srvctl add service -d cubprod -s TAF -r "cubprod1,cubprod2" -e SELECT -m BASIC -P BASIC -z 5 -w 10
2. ตรวจสอบ config service ของเรา
srvctl config service -d cubprod -s TAF
Service name: TAF
Service is enabled
Server pool: cubprod_TAF
Cardinality: 2
Disconnect: false
Service role: PRIMARY
Management policy: AUTOMATIC
DTP transaction: false
AQ HA notifications: false
Failover type: SELECT
Failover method: BASIC
TAF failover retries: 5
TAF failover delay: 10
Connection Load Balancing Goal: LONG
Runtime Load Balancing Goal: NONE
TAF policy specification: BASIC
Edition:
Preferred instances: cubprod1,cubprod2
Available instances:
3. Start the service
srvctl start service -d cubprod -s TAF
4. ลองเช็คด้วย lsnrctl status จะมี TAF service ขึ้นมาทั้ง 2 node
5. ทดลองใช้งานโดยเข้า Service TAF แล้วขณะ SELECT อยู่ให้ลอง kill -9 pmon ของ current instance ดูจะพบว่า Session ได้ถูกย้ายไปอีก Instance นึงโดยอัตโนมัติ
สามารถเช็คได้ด้วย Query
select host_name,instance_name from v$instance;
ปล. ถ้าเป็น SYS user จะขึ้น ORA-03113: end-of-file on communication channel ทีนึงก่อนแล้วมันจะไป connect ใหม่ให้ แต่ถ้าเป็น user ธรรมดามันจะย้ายไปให้เลย
ตัวอย่าง
1. สร้าง service ขึ้นมา 1 ตัวชื่อ TAF เป็นแบบ SELECT type
srvctl add service -d cubprod -s TAF -r "cubprod1,cubprod2" -e SELECT -m BASIC -P BASIC -z 5 -w 10
2. ตรวจสอบ config service ของเรา
srvctl config service -d cubprod -s TAF
Service name: TAF
Service is enabled
Server pool: cubprod_TAF
Cardinality: 2
Disconnect: false
Service role: PRIMARY
Management policy: AUTOMATIC
DTP transaction: false
AQ HA notifications: false
Failover type: SELECT
Failover method: BASIC
TAF failover retries: 5
TAF failover delay: 10
Connection Load Balancing Goal: LONG
Runtime Load Balancing Goal: NONE
TAF policy specification: BASIC
Edition:
Preferred instances: cubprod1,cubprod2
Available instances:
3. Start the service
srvctl start service -d cubprod -s TAF
4. ลองเช็คด้วย lsnrctl status จะมี TAF service ขึ้นมาทั้ง 2 node
5. ทดลองใช้งานโดยเข้า Service TAF แล้วขณะ SELECT อยู่ให้ลอง kill -9 pmon ของ current instance ดูจะพบว่า Session ได้ถูกย้ายไปอีก Instance นึงโดยอัตโนมัติ
สามารถเช็คได้ด้วย Query
select host_name,instance_name from v$instance;
ปล. ถ้าเป็น SYS user จะขึ้น ORA-03113: end-of-file on communication channel ทีนึงก่อนแล้วมันจะไป connect ใหม่ให้ แต่ถ้าเป็น user ธรรมดามันจะย้ายไปให้เลย
วันจันทร์ที่ 22 มิถุนายน พ.ศ. 2558
Query from multiple rows to single line
ฟังก์ชั่น LISTAGG() เป็นฟังก์ชั่นใหม่ในเวอร์ชั่น 11GR2 เพื่อเชื่อม multiple rows ให้เป็น single line
รูปแบบ syntax
LISTAGG( [,]) WITHIN GROUP (ORDER BY ) [OVER (PARTITION BY )]
ปล. สามารถใช้ในการ Analytic ได้เช่นใช้คำสั่ง OVER() clause
ตัวอย่างนี้จะดู username ใน dba_users โดยจะให้มันเชื่อมต่อกันเป็นบรรทัดเดียวและคั่นด้วยเครื่องหมาย ","
รูปแบบ syntax
LISTAGG( [,]) WITHIN GROUP (ORDER BY ) [OVER (PARTITION BY )]
ปล. สามารถใช้ในการ Analytic ได้เช่นใช้คำสั่ง OVER() clause
ตัวอย่างนี้จะดู username ใน dba_users โดยจะให้มันเชื่อมต่อกันเป็นบรรทัดเดียวและคั่นด้วยเครื่องหมาย ","
วันพฤหัสบดีที่ 11 มิถุนายน พ.ศ. 2558
Oracle 12c Multitenant practice
Oracle database 12c Multitenant คือฟีเจอร์ใหม่ที่ทำให้เราสามารถสร้างและจัดการฐานข้อมูลได้หลายตัวมากขึ้นไว้ในฐานข้อมูลใหญ่ตัวเดียวที่เรียกว่า Container Database (CDB) ซึ่งฐานข้อมูลหลายตัวเหล่านั้นเราเรียกว่า Pluggable Databases (PDB)
แต่ละ CDB ประกอบด้วย
- หนึ่ง Root Container ชื่อว่า CDB$ROOT เป็น Master set of data dictionary views ซึ่งมี metadata ที่เกี่ยวข้องกับ root container ตลอดจน pluggable databases ทุกตัวที่อยู่ใน CDB
- หนึ่ง Static seed container ชื่อว่า PDB$SEED โดย container ตัวนี้จะอยู่เป็นอิสระมีหน้าที่เป็นเพียง template เพื่อสร้าง data files และ metadata สำหรับ pluggable databases ตัวใหม่ๆที่จะสร้างขึ้นใน CDB
- Pluggable databases (0 - 252 ตัว) แต่ละ PDB จะจัดการข้อมูลและฟังก์ชั่นต่างๆในตัวเองคล้ายกับ non-CDB database และมันมี data files และ application objects (users , tables , indexes , อื่นๆ) เป็นของตัวเอง เมื่อเราเชื่อมต่อเข้าสู่ PDB ตัวหนึ่งเราจะมองไม่เห็น root container หรือ PDB ตัวอื่นๆ
Pluggable Database Architecture
สร้าง CDB
ถ้าเราจะใช้งาน PDB feature เราต้องสร้าง Database ให้เป็น Container database โดยมีหลายวิธีในการสร้างเช่น
- สร้างโดย SQL CREATE DATABASE command
- ใช้ DBCA
- Generate script จาก DBCA แล้วเอามารันเอง
- ใช้ RMAN เพื่อทำ Duplicate จาก CDB ที่มีอยู่แล้ว
โดยวิธีการสร้างเหล่านี้ขอไม่พูดถึง
ตรวจสอบ CDB ที่ถูกสร้างขึ้นมาแล้ว
- ใช้ sqlplus / as sysdba
- ตรวจสอบคอลัม name และ CDB ถ้าเป็น YES แสดงว่าถูกสร้างเป็น Container
SQL> select name,cdb from v$database;
NAME CDB
--------- ---
KITTICDB YES
- ตอนนี้เราจะมี 2 containers ใน CDB database ของเราก็คือ root กับ seed pluggable database เราสามารถเช็คด้วยการ query
SQL> select con_id,name from v$containers;
CON_ID NAME
---------- ------------------------------
1 CDB$ROOT
2 PDB$SEED
- เราจะมี data files ของทั้ง root และ seed database เราจะตรวจสอบ data files เหล่านั้นด้วย query
select con_id,file_name from cdb_data_files
order by con_id;
Note : ถ้าเราใช้เวอร์ชั่น 12.1.0.2 เราจะไม่เห็นข้อมูลของ seed เพราะมี undocument parameter ใหม่ตัวนึงชื่อว่า EXCLUDE_SEED_CDB_VIEW ค่า default เป็น true
แต่ในตัวอย่างปรับไว้เป็น false จึงทำให้เราเห็นข้อมูลใน seed database ด้วย
- ถ้าเรา query จาก dba_data_files เราจะเห็นแค่ไฟล์ของ database ที่เราใช้งานอยู่ในที่นี้คือ CDB$ROOT
FILE_NAME
---------------------------------------------------------------------
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_SYSTEM_BQHPTC9S_.DBF
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_SYSAUX_BQHPRMY9_.DBF
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_UNDOTBS1_BQHPWG1C_.DBF
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_USERS_BQHPWDRS_.DBF
เชื่อมต่อเข้าสู่ Root Container
เราสามารถเชื่อมต่อโดยเป็น sys as sysdba ได้เหมือนการเชื่อมต่อเข้าฐานข้อมูลแบบ non-CDB ทั่วๆไปเช่น
sqlplus / as sysdba
sqlplus sys@KITTICDB as sysdba
SQL> show user con_id con_name
USER is "SYS"
CON_ID
------------------------------
1
CON_NAME
------------------------------
CDB$ROOT
Start/Stop Root Container
เราสามารถ start/stop CDB ได้เหมือนกับ non-CDB ได้ตามปกติโดยต้องเข้ามาในสิทธิที่สามารถทำการเปิด/ปิด ฐานข้อมูลได้ เช่น
sqlplus / as sysdba
SQL*Plus: Release 12.1.0.2.0 Production on Thu Jun 11 10:37:09 2015
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to an idle instance.
SQL> startup
ORACLE instance started.
Total System Global Area 2583691264 bytes
Fixed Size 3048968 bytes
Variable Size 687868408 bytes
Database Buffers 1879048192 bytes
Redo Buffers 13725696 bytes
Database mounted.
Database opened.
เมื่อ CDB startup แล้วแต่ PDB ทุกตัวจะยังอยู่ในสถานะ Mount อยู่เราจะสั่งให้เปิดทุกตัว เช่น
SQL> alter pluggable database all open;
Pluggable database altered.
หากต้องการปิด PDB ทุกตัวก็สั่ง close โดยทุกตัวจะกลายเป็น Mount mode (ยกเว้น PDB$SEED จะอยู่สถานะ Read Only ตลอด)
SQL> alter pluggable database all close;
Pluggable database altered.
สร้าง PDB และเชื่อมต่อเข้าสู่ PDB
เราสามารถสร้าง PDB ใหม่ได้จาก
- PDB$SEED
- PDB ที่มีอยู่แล้ว
- non-CDB
- Unplugged PDB
1. ลอง Cloning จาก PDB$SEED
Login เข้าสู่ CDB แล้วใช้ SQL สร้าง PDB ขึ้นมาโดยใช้ PDB$SEED เป็น template
SQL> create pluggable database kittipdb1
2 admin user kittiadmin identified by kittiadmin
3 file_name_convert = ('E:\app\kitti_l\oradata\KITTICDB\pdbseed',
4 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB1');
Pluggable database created.
Note. ถ้าใช้ OMF ไม่ต้องใส่ file_name_convert เพราะ Oracle จะกำหนดชื่อและที่อยู่ของไฟล์ให้อัตโนมัติ ส่วน admin user คือ local user ที่มีสิทธิ์จัดการ PDB ได้และได้รับ PDB_DBA role
2. Clone จาก PDB ที่มีอยู่แล้ว
ทำการสร้าง KITTIPDB2 โดย Clone จาก KITTIPDB1
เราต้องปิด PDB ตัวที่เราจะ Clone แล้วเปิดใหม่เป็นแบบ Read Only
SQL> alter pluggable database KITTIPDB1 close;
Pluggable database altered.
SQL> alter pluggable database KITTIPDB1 open read only;
Pluggable database altered.
ทำการ Clone ด้วยคำสั่ง SQL
SQL> create pluggable database KITTIPDB2
2 from KITTIPDB1
3 file_name_convert = ('E:\app\kitti_l\oradata\KITTICDB\KITTIPDB1',
4 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB2')
5 storage (maxsize 4G max_shared_temp_size 80M);
Pluggable database created.
Note. storage clause ในที่นี้คือกำหนดขนาด PDB เต็มที่ไว้มากสุด 4G (maxsize) และ session ใน PDB นี้สามารถใช้ Shared Temporary Tablespace ได้มากสุด 80M (max_shared_temp_size)
3. Clone จาก non-CDB database
ใช้ได้หลายวิธีเช่น DBMS_PDB package , Data Pump(Transport Tablespace), GoldenGate
ในที่นี้จะใช้วิธี DBMS_PDB package แต่มีข้อแม้ว่า database ที่จะ Clone นี้ต้องเวอร์ชั่น 12c ขึ้นไป
เปิด non-CDB แบบ read only
SQL> alter database open read only;
Database altered.
หลังจากนั้นรัน DBMS_PDB เพื่อสร้าง XML file ที่มีโครงสร้างของ database อยู่
SQL> begin
2 dbms_pdb.describe(pdb_descr_file => 'E:\noncdb.xml');
3 end;
4 /
PL/SQL procedure successfully completed.
หลังจากไฟล์ XML ถูกสร้างแล้วให้ปิด non-CDB
SQL> shutdown immediate;
ปรับ ORACLE_SID ให้ชี้ไปที่ CDB database ที่เราจะ Clone non-CDB ไปและเข้า sys as sysdba
sqlplus / as sysdba
ตอนนี้เราอยู่ใน CDB database แล้วเราสามารถเช็คก่อนได้ว่า non-CDB ที่เราจะ Clone นั้น compatible กับ CDB database ของเราไหมด้วย DBMS_PDB.CHECK_PLUG_COMPATIBILITY
SQL> set serveroutput on
SQL> declare
2 hold_var boolean;
3 begin
4 hold_var := dbms_pdb.check_plug_compatibility(pdb_descr_file => 'E:\noncdb.xml');
5 if hold_var then
6 dbms_output.put_line('YES');
7 else
8 dbms_output.put_line('NO');
9 end if;
10 end;
11 /
YES
PL/SQL procedure successfully completed.
จากการทดสอบผลคือ YES แสดงว่าไม่มีปัญหาเกี่ยวกับ compatibility แต่ถ้าเป็น NO แสดงว่าอาจมีอะไรผิดพลาด เราสามารถดู PDB_PLUG_IN_VIOLATIONS view เพื่อดูรายละเอียดได้ว่าทำไมถึงไม่ compatibility
ต่อมาใช้คำสั่ง SQL เพื่อสร้าง PDB ขึ้นมาจาก non-CDB โดยเราต้องระบุชื่อและที่อยู่ของ XML file ของ non-CDB , ที่อยู่ของ non-CDB data files , และที่อยู่ใหม่ของ PDB
SQL> create pluggable database KITTIPDB2FROMnonCDB
2 using 'E:\noncdb.xml'
3 copy
4 file_name_convert = ('E:\app\kitti_l\oradata\KITTInonCDB',
5 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB3FROMnonCDB');
Pluggable database created.
เสร็จแล้วลองเชื่อมต่อเข้า PDB ใหม่
SQL> alter session set container=KITTIPDB2FROMnonCDB;
Session altered.
สุดท้ายรันสคริปต์นี้ก็เสร็จสมบูรณ์
@?\rdbms\admin\noncdb_to_pdb.sql
หลังจากนั้น database ควรจะสามารถเปิดขึ้นมาได้ตามปกติ
Unplugging a PDB
ก่อนที่เราจะเอา PDB ไปปลั๊กเข้ากับ CDB อื่นเราต้องทำการ Unplug มันออกจาก CDB ตัวเดิมเสียก่อน
เมื่อเรา Unplug ออกจาก CDB แล้วเราจะได้ XML file มาโดยไฟล์นี้จะเป็นข้อมูล metadata ของ PDB ตัวนั้นๆและสามารถนำไปใช้ Plug เข้าไปที่ CDB ตัวอื่นได้
ปิด PDB ตัวที่จะ Unplug ก่อน
สั่ง Unplug ด้วยคำสั่ง alter pluggable database ... unplug into '....xml';
SQL> alter pluggable database kittipdb2 unplug into 'E:\kittipdb2.xml';
Pluggable database altered.
Note. เมื่อ Unplugged PDB เสร็จแล้วเราต้อง Drop PDB ตัวนั้นก่อนที่จะทำการ Plug เข้ามาสู่ CDB ตัวเดิม (แต่ต้องใช้ keep datafiles option เพราะต้องใช้ data files เดิม)
SQL> drop pluggable database kittipdb2 keep datafiles;
Pluggable database dropped.
Note2. เราสามารถใช้ DBMS_PDB package เพื่อตรวจสอบ compatible ก่อนได้เหมือนกับการ Clone non-CDB to PDB ด้านบน
ในการ Plug เข้าไปใน CDB เราจะทำด้วย SQL statement CREATE PLUGGABLE DATABASE ... และใช้ 2 คำสั่งนี้ในการระบุข้อมูลลงไปคือ
USING clause : ใช้ในการระบุที่อยู่ของ XML file
COPY FILE_NAME_CONVERT clause : ใช้ในการกำหนดที่อยู่ data files ใหม่ในกรณีที่ path ไม่เป็นเหมือนเดิม
แต่ตอนนี้เราจะทำการ Plug เข้าสู่ CDB ตัวเดิมและใช้ data files location เดิมจึงสามารถใช้ NOCOPY clause ได้
SQL> create pluggable database kittipdb2
2 using 'E:\kittipdb2.xml'
3 nocopy;
Pluggable database created.
เมื่อ Plug เข้ามาแล้วก็เปิด database ได้ตามปกติ
SQL> alter pluggable database kittipdb2 open;
Pluggable database altered.
ลองเชื่อมต่อเข้าสู่ PDB ต่างๆ
วิธีแรกใช้ alter session
SQL> alter session set container=KITTIPDB2;
Session altered.
SQL> show con_name
CON_NAME
------------------------------
KITTIPDB2
วิธีที่สองเข้าผ่าน easy connect หรือ tnsnames
sqlplus sys/oracle@localhost:1521/KITTIPDB2 as sysdba
sqlplus sys/oracle@KITTIPDB2 as sysdba
เช็คสถานะของ PDB
ใช้คำสั่ง SQL ถ้าอยู่ที่ CDB จะเห็น PDB ทุกตัวแต่ถ้าอยู่ที่ PDB ตัวไหนจะเห็นแค่ตัวนั้น
SQL> select con_id,name,open_mode,restricted from v$pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 KITTIPDB2 READ WRITE NO
4 KITTIPDB1 READ WRITE NO
5 KITTIPDB2FROMNONCDB READ WRITE NO
ตรวจสอบว่า parameter ตัวไหนบ้างที่สามารถแก้ไขได้ในระดับ PDB
select name
from v$parameter
where ispdb_modifiable='TRUE'
order by name;
เปลี่ยนชื่อ PDB
เราสามารถเปลี่ยนชื่อ PDB ได้โดยทำการปิดแล้วเปิดใหม่เป็นโหมด restrict เสร็จแล้วสั่งเปลี่ยนชื่อด้วยคำสั่งเช่น
SQL> alter session set container=kittipdb2fromnoncdb;
Session altered.
SQL> shutdown immediate
Pluggable Database closed.
SQL> startup restrict;
Pluggable Database opened.
SQL> alter pluggable database KITTIPDB2FROMnonCDB rename global_name to KITTIPDB3;
Pluggable database altered.
Common Users
มี User 2 ประเภทที่ใช้ใน Pluggable database environment คือ local user กับ common user
local user คือ user ปกติที่ใช้ใน PDB โดยการจัดการจะเหมือนระบบ non-CDB ทั่วๆไป
และ common user เมื่อสร้างเสร็จจะอยู่ใน root container และทุก pluggable database ตลอดจน pluggable database ที่ถูกสร้างขึ้นในอนาคตอีกด้วย
Note. SYS กับ SYSTEM คือ common users ที่ Oracle สร้างให้โดยอัตโนมัติใน Pluggable environment
Common user จะถูกสร้างโดยใช้ C## หรือ c## นำหน้าชื่อ เช่น
sqlplus / as sysdba
SQL> create user c##kitti identified by kitti;
User created.
Common user จะมีสิทธิ์ต่างๆกับไหน PDB ได้ต้องถูก grant จากใน PDB นั้นเท่านั้น ถ้าเราต้องการ grant ให้มีสิทธิ์กับทุกๆ PDB เราต้องสร้าง Common Role แล้ว grant ให้ common user
Common Roles
จะคล้ายกับการสร้าง Common user ที่จะอยู่ในทุก PDB ใน Root container นั้นตลอดจน PDB ที่ถูกสร้างขึ้นในอนาคต และเหมือนกับกับ Common user อีกก็คือ Common role ต้องสร้างด้วย C## หรือ c## นำหน้า ตัวอย่างเช่น
sqlplus / as sysdba
SQL> create role c##dbaprivs container=all;
Role created.
ต่อมาเราสามารถกำหนดสิทธิ์ต่างๆให้กับ common role นี้ได้ เช่น
SQL> grant dba to c##dbaprivs container=all;
Grant succeeded.
เท่านี้ role นี้ก็จะมีสิทธิ์ dba (มาจาก dba role) ที่สามารถใช้งานได้ทุก PDB ต่อมาเราก็จะ grant role นี้ให้กับ common user
SQL> grant c##dbaprivs to c##kitti container=all;
Grant succeeded.
ตอนนี้ c##kitti ก็สามารถจัดการฐานข้อมูลด้วยสิทธิ์ c##dbaprivs(from dba role) ได้ทุก PDB แล้ว
RMAN Backup and Recovery
ในขณะที่เราเชื่อมต่อกับ CDB(Root contaner) เราสามารถ backup ได้ทุก data file ใน database หรือแค่ root container data files , a specific pluggable database , specific tablespaces or data files , or a combination of these
แต่ในขณะที่เราเชื่อมต่อกับ PDB เราจะสามารถ backup ได้แค่ data files ของ PDB ที่เราเชื่อมต่ออยู่
While Connected to the Root container
เช็คก่อนว่าเราเชื่อมต่อไปที่ Root container หรือยัง
RMAN> SELECT SYS_CONTEXT('USERENV', 'CON_ID') AS con_id,
2> SYS_CONTEXT('USERENV', 'CON_NAME') AS cur_container,
3> SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS cur_user
4> FROM DUAL;
using target database control file instead of recovery catalog
CON_ID CUR_CONTAINER CUR_USER
---------------------------- ---------------------------- ----------------------------
1 CDB$ROOT SYS
ลอง backup ทุก data file ทั้ง root container database และ pluggable database ในนั้น
RMAN> backup database;
ถ้าเราอยาก backup เฉพาะของ root container ให้ใส่ "root"
RMAN> backup database root;
เราสามารถ backup เฉพาะ PDB ที่เราต้องการได้เช่นกัน
RMAN> backup pluggable database kittipdb1;
และเราก็ backup แบบเจาะจง tablespace ใน PDB ที่เราต้องการได้ด้วย
RMAN> backup tablespace kittipdb1:system,sysaux;
สุดท้ายนี้เราสามารถ backup data file ของ root container database หรือ pluggable database โดยการใส่พาธและชื่อลงไปได้เลย
RMAN> backup datafile 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB2\SYSTEM01.DBF';
While Connected to a Pluggable database
เราสามารถเชื่อมต่อเข้า PDB ได้เลยจาก RMAN เช่น
rman target sys/oracle@KITTIPDB1
หลังจากเชื่อมต่อเข้ามาแล้วเราสามารถ backup ได้เฉพาะ data file ของ PDB นั้น ดังนั้นเมื่อเราสั่ง
RMAN> backup database;
จะเป็นการ backup เพียงแค่ทุก data file ของ PDB นั้นๆ
หรือ
RMAN> backup tablespace system;
ก็เป็นการ backup system tablespace's data file ของ PDB นั้นๆ เช่นกัน
Complete Recovery
การกู้ทั้ง CDB จะคล้ายกับการกู้ non-CDB แต่มันจะกู้ PDB ที่เกี่ยวข้องมาด้วย
RMAN> run {
2> shutdown immediate; #or abort if failed
3> startup mount;
4> restore database;
5> recover database;
6> alter database open;
7> }
Root Container Complete Recovery
จะให้ผลลัพธ์เหมือนกับการกู้ทั้ง CDB
RMAN> run {
2> shutdown immediate; #or abort if failed
3> startup mount;
4> restore database root;
5> recover database root;
6> alter database open;
7> }
Pluggable Database Complete Recovery
มี 2 วิธีคือ
1.เชื่อมต่ออยู่กับ CDB เราสามารถเลือก PDB ที่จะกู้ได้เลย
RMAN> run {
2> alter pluggable database kittipdb1,kittipdb2 close;
3> restore pluggable database kittipdb1,kittipdb2;
4> recover pluggable database kittipdb1,kittipdb2;
5> alter pluggable database kittipdb1,kittipdb2 open;
6> }
2.ถ้าเชื่อมต่อกับ PDB ก็จะกู้ได้เฉพาะ PDB นั้น
RMAN> run {
2> shutdown immediate;
3> restore database;
4> recover database;
5> startup;
6> }
CDB Point In Time Recovery
จะเหมือนกับของ non-CDB แค่เพิ่มเติมคือเราได้ทำ PITR ทุก PDB ไปด้วย
RMAN> run {
2> shutdown immediate; #or abort if failed
3> startup mount;
4> restore database;
5> recover database until time "to_date('16/06/2015 17:00','DD/MM/YYYY HH24:M
I')";
6> alter database open resetlogs;
7> }
PDB Point In Time Recovery
ทำคล้ายกับ Complete ตรงที่สามารถกู้ PDB กี่ตัวก็ได้ถ้าเราเชื่อมต่ออยู่ที่ Root Container
แต่ถ้าเชื่อมต่ออยู่ที่ PDB ไหนก็จะกู้ได้เฉพาะ PDB นั้น
RMAN> run {
2> alter pluggable database kittipdb1,kittipdb2 close;
3> restore pluggable database kittipdb1,kittipdb2;
4> recover pluggable database kittipdb1,kittipdb2 until time "to_date('16/06/2015 17:00','DD/MM/YYYY HH24:M
I')";
5> alter pluggable database kittipdb1,kittipdb2 open resetlogs;
6> }
Note. กรณีนี้ Resetlogs option จะไม่ได้ทำอะไรกับ Redo log file แต่แค่สร้าง DB incarnation ใหม่
ศึกษามาจากหนังสือ e-book : Pro Oracle Database 12c Administration, 2nd Edition
แต่ละ CDB ประกอบด้วย
- หนึ่ง Root Container ชื่อว่า CDB$ROOT เป็น Master set of data dictionary views ซึ่งมี metadata ที่เกี่ยวข้องกับ root container ตลอดจน pluggable databases ทุกตัวที่อยู่ใน CDB
- หนึ่ง Static seed container ชื่อว่า PDB$SEED โดย container ตัวนี้จะอยู่เป็นอิสระมีหน้าที่เป็นเพียง template เพื่อสร้าง data files และ metadata สำหรับ pluggable databases ตัวใหม่ๆที่จะสร้างขึ้นใน CDB
- Pluggable databases (0 - 252 ตัว) แต่ละ PDB จะจัดการข้อมูลและฟังก์ชั่นต่างๆในตัวเองคล้ายกับ non-CDB database และมันมี data files และ application objects (users , tables , indexes , อื่นๆ) เป็นของตัวเอง เมื่อเราเชื่อมต่อเข้าสู่ PDB ตัวหนึ่งเราจะมองไม่เห็น root container หรือ PDB ตัวอื่นๆ
Pluggable Database Architecture
สร้าง CDB
ถ้าเราจะใช้งาน PDB feature เราต้องสร้าง Database ให้เป็น Container database โดยมีหลายวิธีในการสร้างเช่น
- สร้างโดย SQL CREATE DATABASE command
- ใช้ DBCA
- Generate script จาก DBCA แล้วเอามารันเอง
- ใช้ RMAN เพื่อทำ Duplicate จาก CDB ที่มีอยู่แล้ว
โดยวิธีการสร้างเหล่านี้ขอไม่พูดถึง
ตรวจสอบ CDB ที่ถูกสร้างขึ้นมาแล้ว
- ใช้ sqlplus / as sysdba
- ตรวจสอบคอลัม name และ CDB ถ้าเป็น YES แสดงว่าถูกสร้างเป็น Container
SQL> select name,cdb from v$database;
NAME CDB
--------- ---
KITTICDB YES
- ตอนนี้เราจะมี 2 containers ใน CDB database ของเราก็คือ root กับ seed pluggable database เราสามารถเช็คด้วยการ query
SQL> select con_id,name from v$containers;
CON_ID NAME
---------- ------------------------------
1 CDB$ROOT
2 PDB$SEED
- เราจะมี data files ของทั้ง root และ seed database เราจะตรวจสอบ data files เหล่านั้นด้วย query
select con_id,file_name from cdb_data_files
order by con_id;
Note : ถ้าเราใช้เวอร์ชั่น 12.1.0.2 เราจะไม่เห็นข้อมูลของ seed เพราะมี undocument parameter ใหม่ตัวนึงชื่อว่า EXCLUDE_SEED_CDB_VIEW ค่า default เป็น true
แต่ในตัวอย่างปรับไว้เป็น false จึงทำให้เราเห็นข้อมูลใน seed database ด้วย
- ถ้าเรา query จาก dba_data_files เราจะเห็นแค่ไฟล์ของ database ที่เราใช้งานอยู่ในที่นี้คือ CDB$ROOT
FILE_NAME
---------------------------------------------------------------------
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_SYSTEM_BQHPTC9S_.DBF
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_SYSAUX_BQHPRMY9_.DBF
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_UNDOTBS1_BQHPWG1C_.DBF
E:\APP\KITTI_L\ORADATA\KITTICDB\DATAFILE\O1_MF_USERS_BQHPWDRS_.DBF
เชื่อมต่อเข้าสู่ Root Container
เราสามารถเชื่อมต่อโดยเป็น sys as sysdba ได้เหมือนการเชื่อมต่อเข้าฐานข้อมูลแบบ non-CDB ทั่วๆไปเช่น
sqlplus / as sysdba
sqlplus sys@KITTICDB as sysdba
SQL> show user con_id con_name
USER is "SYS"
CON_ID
------------------------------
1
CON_NAME
------------------------------
CDB$ROOT
Start/Stop Root Container
เราสามารถ start/stop CDB ได้เหมือนกับ non-CDB ได้ตามปกติโดยต้องเข้ามาในสิทธิที่สามารถทำการเปิด/ปิด ฐานข้อมูลได้ เช่น
sqlplus / as sysdba
SQL*Plus: Release 12.1.0.2.0 Production on Thu Jun 11 10:37:09 2015
Copyright (c) 1982, 2014, Oracle. All rights reserved.
Connected to an idle instance.
SQL> startup
ORACLE instance started.
Total System Global Area 2583691264 bytes
Fixed Size 3048968 bytes
Variable Size 687868408 bytes
Database Buffers 1879048192 bytes
Redo Buffers 13725696 bytes
Database mounted.
Database opened.
เมื่อ CDB startup แล้วแต่ PDB ทุกตัวจะยังอยู่ในสถานะ Mount อยู่เราจะสั่งให้เปิดทุกตัว เช่น
SQL> alter pluggable database all open;
Pluggable database altered.
หากต้องการปิด PDB ทุกตัวก็สั่ง close โดยทุกตัวจะกลายเป็น Mount mode (ยกเว้น PDB$SEED จะอยู่สถานะ Read Only ตลอด)
SQL> alter pluggable database all close;
Pluggable database altered.
สร้าง PDB และเชื่อมต่อเข้าสู่ PDB
เราสามารถสร้าง PDB ใหม่ได้จาก
- PDB$SEED
- PDB ที่มีอยู่แล้ว
- non-CDB
- Unplugged PDB
1. ลอง Cloning จาก PDB$SEED
Login เข้าสู่ CDB แล้วใช้ SQL สร้าง PDB ขึ้นมาโดยใช้ PDB$SEED เป็น template
SQL> create pluggable database kittipdb1
2 admin user kittiadmin identified by kittiadmin
3 file_name_convert = ('E:\app\kitti_l\oradata\KITTICDB\pdbseed',
4 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB1');
Pluggable database created.
Note. ถ้าใช้ OMF ไม่ต้องใส่ file_name_convert เพราะ Oracle จะกำหนดชื่อและที่อยู่ของไฟล์ให้อัตโนมัติ ส่วน admin user คือ local user ที่มีสิทธิ์จัดการ PDB ได้และได้รับ PDB_DBA role
2. Clone จาก PDB ที่มีอยู่แล้ว
ทำการสร้าง KITTIPDB2 โดย Clone จาก KITTIPDB1
เราต้องปิด PDB ตัวที่เราจะ Clone แล้วเปิดใหม่เป็นแบบ Read Only
SQL> alter pluggable database KITTIPDB1 close;
Pluggable database altered.
SQL> alter pluggable database KITTIPDB1 open read only;
Pluggable database altered.
ทำการ Clone ด้วยคำสั่ง SQL
SQL> create pluggable database KITTIPDB2
2 from KITTIPDB1
3 file_name_convert = ('E:\app\kitti_l\oradata\KITTICDB\KITTIPDB1',
4 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB2')
5 storage (maxsize 4G max_shared_temp_size 80M);
Pluggable database created.
Note. storage clause ในที่นี้คือกำหนดขนาด PDB เต็มที่ไว้มากสุด 4G (maxsize) และ session ใน PDB นี้สามารถใช้ Shared Temporary Tablespace ได้มากสุด 80M (max_shared_temp_size)
3. Clone จาก non-CDB database
ใช้ได้หลายวิธีเช่น DBMS_PDB package , Data Pump(Transport Tablespace), GoldenGate
ในที่นี้จะใช้วิธี DBMS_PDB package แต่มีข้อแม้ว่า database ที่จะ Clone นี้ต้องเวอร์ชั่น 12c ขึ้นไป
เปิด non-CDB แบบ read only
SQL> alter database open read only;
Database altered.
หลังจากนั้นรัน DBMS_PDB เพื่อสร้าง XML file ที่มีโครงสร้างของ database อยู่
SQL> begin
2 dbms_pdb.describe(pdb_descr_file => 'E:\noncdb.xml');
3 end;
4 /
PL/SQL procedure successfully completed.
หลังจากไฟล์ XML ถูกสร้างแล้วให้ปิด non-CDB
SQL> shutdown immediate;
ปรับ ORACLE_SID ให้ชี้ไปที่ CDB database ที่เราจะ Clone non-CDB ไปและเข้า sys as sysdba
sqlplus / as sysdba
ตอนนี้เราอยู่ใน CDB database แล้วเราสามารถเช็คก่อนได้ว่า non-CDB ที่เราจะ Clone นั้น compatible กับ CDB database ของเราไหมด้วย DBMS_PDB.CHECK_PLUG_COMPATIBILITY
SQL> set serveroutput on
SQL> declare
2 hold_var boolean;
3 begin
4 hold_var := dbms_pdb.check_plug_compatibility(pdb_descr_file => 'E:\noncdb.xml');
5 if hold_var then
6 dbms_output.put_line('YES');
7 else
8 dbms_output.put_line('NO');
9 end if;
10 end;
11 /
YES
PL/SQL procedure successfully completed.
จากการทดสอบผลคือ YES แสดงว่าไม่มีปัญหาเกี่ยวกับ compatibility แต่ถ้าเป็น NO แสดงว่าอาจมีอะไรผิดพลาด เราสามารถดู PDB_PLUG_IN_VIOLATIONS view เพื่อดูรายละเอียดได้ว่าทำไมถึงไม่ compatibility
ต่อมาใช้คำสั่ง SQL เพื่อสร้าง PDB ขึ้นมาจาก non-CDB โดยเราต้องระบุชื่อและที่อยู่ของ XML file ของ non-CDB , ที่อยู่ของ non-CDB data files , และที่อยู่ใหม่ของ PDB
SQL> create pluggable database KITTIPDB2FROMnonCDB
2 using 'E:\noncdb.xml'
3 copy
4 file_name_convert = ('E:\app\kitti_l\oradata\KITTInonCDB',
5 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB3FROMnonCDB');
Pluggable database created.
เสร็จแล้วลองเชื่อมต่อเข้า PDB ใหม่
SQL> alter session set container=KITTIPDB2FROMnonCDB;
Session altered.
สุดท้ายรันสคริปต์นี้ก็เสร็จสมบูรณ์
@?\rdbms\admin\noncdb_to_pdb.sql
หลังจากนั้น database ควรจะสามารถเปิดขึ้นมาได้ตามปกติ
Unplugging a PDB
ก่อนที่เราจะเอา PDB ไปปลั๊กเข้ากับ CDB อื่นเราต้องทำการ Unplug มันออกจาก CDB ตัวเดิมเสียก่อน
เมื่อเรา Unplug ออกจาก CDB แล้วเราจะได้ XML file มาโดยไฟล์นี้จะเป็นข้อมูล metadata ของ PDB ตัวนั้นๆและสามารถนำไปใช้ Plug เข้าไปที่ CDB ตัวอื่นได้
ปิด PDB ตัวที่จะ Unplug ก่อน
สั่ง Unplug ด้วยคำสั่ง alter pluggable database ... unplug into '....xml';
SQL> alter pluggable database kittipdb2 unplug into 'E:\kittipdb2.xml';
Pluggable database altered.
Note. เมื่อ Unplugged PDB เสร็จแล้วเราต้อง Drop PDB ตัวนั้นก่อนที่จะทำการ Plug เข้ามาสู่ CDB ตัวเดิม (แต่ต้องใช้ keep datafiles option เพราะต้องใช้ data files เดิม)
SQL> drop pluggable database kittipdb2 keep datafiles;
Pluggable database dropped.
Note2. เราสามารถใช้ DBMS_PDB package เพื่อตรวจสอบ compatible ก่อนได้เหมือนกับการ Clone non-CDB to PDB ด้านบน
ในการ Plug เข้าไปใน CDB เราจะทำด้วย SQL statement CREATE PLUGGABLE DATABASE ... และใช้ 2 คำสั่งนี้ในการระบุข้อมูลลงไปคือ
USING clause : ใช้ในการระบุที่อยู่ของ XML file
COPY FILE_NAME_CONVERT clause : ใช้ในการกำหนดที่อยู่ data files ใหม่ในกรณีที่ path ไม่เป็นเหมือนเดิม
แต่ตอนนี้เราจะทำการ Plug เข้าสู่ CDB ตัวเดิมและใช้ data files location เดิมจึงสามารถใช้ NOCOPY clause ได้
SQL> create pluggable database kittipdb2
2 using 'E:\kittipdb2.xml'
3 nocopy;
Pluggable database created.
เมื่อ Plug เข้ามาแล้วก็เปิด database ได้ตามปกติ
SQL> alter pluggable database kittipdb2 open;
Pluggable database altered.
ลองเชื่อมต่อเข้าสู่ PDB ต่างๆ
วิธีแรกใช้ alter session
SQL> alter session set container=KITTIPDB2;
Session altered.
SQL> show con_name
CON_NAME
------------------------------
KITTIPDB2
วิธีที่สองเข้าผ่าน easy connect หรือ tnsnames
sqlplus sys/oracle@localhost:1521/KITTIPDB2 as sysdba
sqlplus sys/oracle@KITTIPDB2 as sysdba
เช็คสถานะของ PDB
ใช้คำสั่ง SQL ถ้าอยู่ที่ CDB จะเห็น PDB ทุกตัวแต่ถ้าอยู่ที่ PDB ตัวไหนจะเห็นแค่ตัวนั้น
SQL> select con_id,name,open_mode,restricted from v$pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 KITTIPDB2 READ WRITE NO
4 KITTIPDB1 READ WRITE NO
5 KITTIPDB2FROMNONCDB READ WRITE NO
ตรวจสอบว่า parameter ตัวไหนบ้างที่สามารถแก้ไขได้ในระดับ PDB
select name
from v$parameter
where ispdb_modifiable='TRUE'
order by name;
เปลี่ยนชื่อ PDB
เราสามารถเปลี่ยนชื่อ PDB ได้โดยทำการปิดแล้วเปิดใหม่เป็นโหมด restrict เสร็จแล้วสั่งเปลี่ยนชื่อด้วยคำสั่งเช่น
SQL> alter session set container=kittipdb2fromnoncdb;
Session altered.
SQL> shutdown immediate
Pluggable Database closed.
SQL> startup restrict;
Pluggable Database opened.
SQL> alter pluggable database KITTIPDB2FROMnonCDB rename global_name to KITTIPDB3;
Pluggable database altered.
Common Users
มี User 2 ประเภทที่ใช้ใน Pluggable database environment คือ local user กับ common user
local user คือ user ปกติที่ใช้ใน PDB โดยการจัดการจะเหมือนระบบ non-CDB ทั่วๆไป
และ common user เมื่อสร้างเสร็จจะอยู่ใน root container และทุก pluggable database ตลอดจน pluggable database ที่ถูกสร้างขึ้นในอนาคตอีกด้วย
Note. SYS กับ SYSTEM คือ common users ที่ Oracle สร้างให้โดยอัตโนมัติใน Pluggable environment
Common user จะถูกสร้างโดยใช้ C## หรือ c## นำหน้าชื่อ เช่น
sqlplus / as sysdba
SQL> create user c##kitti identified by kitti;
User created.
Common user จะมีสิทธิ์ต่างๆกับไหน PDB ได้ต้องถูก grant จากใน PDB นั้นเท่านั้น ถ้าเราต้องการ grant ให้มีสิทธิ์กับทุกๆ PDB เราต้องสร้าง Common Role แล้ว grant ให้ common user
Common Roles
จะคล้ายกับการสร้าง Common user ที่จะอยู่ในทุก PDB ใน Root container นั้นตลอดจน PDB ที่ถูกสร้างขึ้นในอนาคต และเหมือนกับกับ Common user อีกก็คือ Common role ต้องสร้างด้วย C## หรือ c## นำหน้า ตัวอย่างเช่น
sqlplus / as sysdba
SQL> create role c##dbaprivs container=all;
Role created.
ต่อมาเราสามารถกำหนดสิทธิ์ต่างๆให้กับ common role นี้ได้ เช่น
SQL> grant dba to c##dbaprivs container=all;
Grant succeeded.
เท่านี้ role นี้ก็จะมีสิทธิ์ dba (มาจาก dba role) ที่สามารถใช้งานได้ทุก PDB ต่อมาเราก็จะ grant role นี้ให้กับ common user
SQL> grant c##dbaprivs to c##kitti container=all;
Grant succeeded.
ตอนนี้ c##kitti ก็สามารถจัดการฐานข้อมูลด้วยสิทธิ์ c##dbaprivs(from dba role) ได้ทุก PDB แล้ว
RMAN Backup and Recovery
ในขณะที่เราเชื่อมต่อกับ CDB(Root contaner) เราสามารถ backup ได้ทุก data file ใน database หรือแค่ root container data files , a specific pluggable database , specific tablespaces or data files , or a combination of these
แต่ในขณะที่เราเชื่อมต่อกับ PDB เราจะสามารถ backup ได้แค่ data files ของ PDB ที่เราเชื่อมต่ออยู่
While Connected to the Root container
เช็คก่อนว่าเราเชื่อมต่อไปที่ Root container หรือยัง
RMAN> SELECT SYS_CONTEXT('USERENV', 'CON_ID') AS con_id,
2> SYS_CONTEXT('USERENV', 'CON_NAME') AS cur_container,
3> SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AS cur_user
4> FROM DUAL;
using target database control file instead of recovery catalog
CON_ID CUR_CONTAINER CUR_USER
---------------------------- ---------------------------- ----------------------------
1 CDB$ROOT SYS
ลอง backup ทุก data file ทั้ง root container database และ pluggable database ในนั้น
RMAN> backup database;
ถ้าเราอยาก backup เฉพาะของ root container ให้ใส่ "root"
RMAN> backup database root;
เราสามารถ backup เฉพาะ PDB ที่เราต้องการได้เช่นกัน
RMAN> backup pluggable database kittipdb1;
และเราก็ backup แบบเจาะจง tablespace ใน PDB ที่เราต้องการได้ด้วย
RMAN> backup tablespace kittipdb1:system,sysaux;
สุดท้ายนี้เราสามารถ backup data file ของ root container database หรือ pluggable database โดยการใส่พาธและชื่อลงไปได้เลย
RMAN> backup datafile 'E:\app\kitti_l\oradata\KITTICDB\KITTIPDB2\SYSTEM01.DBF';
While Connected to a Pluggable database
เราสามารถเชื่อมต่อเข้า PDB ได้เลยจาก RMAN เช่น
rman target sys/oracle@KITTIPDB1
หลังจากเชื่อมต่อเข้ามาแล้วเราสามารถ backup ได้เฉพาะ data file ของ PDB นั้น ดังนั้นเมื่อเราสั่ง
RMAN> backup database;
จะเป็นการ backup เพียงแค่ทุก data file ของ PDB นั้นๆ
หรือ
RMAN> backup tablespace system;
ก็เป็นการ backup system tablespace's data file ของ PDB นั้นๆ เช่นกัน
Complete Recovery
การกู้ทั้ง CDB จะคล้ายกับการกู้ non-CDB แต่มันจะกู้ PDB ที่เกี่ยวข้องมาด้วย
RMAN> run {
2> shutdown immediate; #or abort if failed
3> startup mount;
4> restore database;
5> recover database;
6> alter database open;
7> }
Root Container Complete Recovery
จะให้ผลลัพธ์เหมือนกับการกู้ทั้ง CDB
RMAN> run {
2> shutdown immediate; #or abort if failed
3> startup mount;
4> restore database root;
5> recover database root;
6> alter database open;
7> }
Pluggable Database Complete Recovery
มี 2 วิธีคือ
1.เชื่อมต่ออยู่กับ CDB เราสามารถเลือก PDB ที่จะกู้ได้เลย
RMAN> run {
2> alter pluggable database kittipdb1,kittipdb2 close;
3> restore pluggable database kittipdb1,kittipdb2;
4> recover pluggable database kittipdb1,kittipdb2;
5> alter pluggable database kittipdb1,kittipdb2 open;
6> }
2.ถ้าเชื่อมต่อกับ PDB ก็จะกู้ได้เฉพาะ PDB นั้น
RMAN> run {
2> shutdown immediate;
3> restore database;
4> recover database;
5> startup;
6> }
CDB Point In Time Recovery
จะเหมือนกับของ non-CDB แค่เพิ่มเติมคือเราได้ทำ PITR ทุก PDB ไปด้วย
RMAN> run {
2> shutdown immediate; #or abort if failed
3> startup mount;
4> restore database;
5> recover database until time "to_date('16/06/2015 17:00','DD/MM/YYYY HH24:M
I')";
6> alter database open resetlogs;
7> }
PDB Point In Time Recovery
ทำคล้ายกับ Complete ตรงที่สามารถกู้ PDB กี่ตัวก็ได้ถ้าเราเชื่อมต่ออยู่ที่ Root Container
แต่ถ้าเชื่อมต่ออยู่ที่ PDB ไหนก็จะกู้ได้เฉพาะ PDB นั้น
RMAN> run {
2> alter pluggable database kittipdb1,kittipdb2 close;
3> restore pluggable database kittipdb1,kittipdb2;
4> recover pluggable database kittipdb1,kittipdb2 until time "to_date('16/06/2015 17:00','DD/MM/YYYY HH24:M
I')";
5> alter pluggable database kittipdb1,kittipdb2 open resetlogs;
6> }
Note. กรณีนี้ Resetlogs option จะไม่ได้ทำอะไรกับ Redo log file แต่แค่สร้าง DB incarnation ใหม่
ศึกษามาจากหนังสือ e-book : Pro Oracle Database 12c Administration, 2nd Edition
สมัครสมาชิก:
บทความ (Atom)
































