วันจันทร์ที่ 20 เมษายน พ.ศ. 2558

กู้ Tablespace ที่ถูก drop ด้วย Flashback Database

เราสามารถกู้ความผิดพลาดในการ drop tablespace ได้ด้วย flashback database ตามนี้

SQL> alter database flashback on;

Database altered.

SQL> alter database open;

Database altered.

SQL> create tablespace kitti_tbs datafile '/u01/app/oracle/oradata/ORACLE/kitti01.dbf' size 10m;

Tablespace created.

SQL> create table kitti_tbl (id number) tablespace kitti_tbs;

Table created.

SQL> select current_scn from v$database;

CURRENT_SCN
-----------
     471727

SQL> drop tablespace kitti_tbs including contents and datafiles;

Tablespace dropped.

SQL> shutdown immediate

SQL> startup mount

SQL> flashback database to scn 471727;

Flashback complete.

--ขั้นตอนนี้ต้องเช็ค datafile ก่อนเพราะมันจะสร้างมาให้ในชื่อแปลกๆ

SQL> select name from v$datafile;

NAME
--------------------------------------------------------------------------------
/u01/app/oracle/oradata/ORACLE/system01.dbf
/u01/app/oracle/oradata/ORACLE/sysaux01.dbf
/u01/app/oracle/oradata/ORACLE/undotbs01.dbf
/u01/app/oracle/oradata/ORACLE/users01.dbf
/u01/app/oracle/product/11.2.0/dbhome_1/dbs/UNNAMED00005      <---- ชื่อแปลกๆที่มันสร้างมาให้

--สร้างใหม่ไปไว้ path เดิมโดยลอกไฟล์ที่มันสร้างมาให้

SQL> alter database create datafile '/u01/app/oracle/product/11.2.0/dbhome_1/dbs/UNNAMED00005' as '/u01/app/oracle/oradata/ORACLE/kitti01.dbf';

Database altered.

--สั่งให้ datafile online

SQL> alter tablespace kitti_tbs datafile online;

Tablespace altered.

--Flashback ซ้ำเข้าไปอีกที

SQL> flashback database to scn 471727;


Flashback complete.

--เปิด database ด้วย resetlogs option

SQL> alter database open resetlogs;


Database altered.

--ลอง query ดู tablespace

SQL> select name from v$tablespace;

NAME
------------------------------
SYSTEM
SYSAUX
UNDOTBS1
TEMP
USERS

KITTI_TBS   <---ได้ tablespace กลับคืนมาแล้ว

--ลอง query ดู table ของเรา

SQL> select * from kitti_tbl;


no rows selected

ได้ table กลับคืนมาแล้ว

วันพฤหัสบดีที่ 9 เมษายน พ.ศ. 2558

ติดตั้ง Oracle 12c RAC บน Oracle Linux 6.5 โดยใช้ VirtualBox

ในที่นี้จะสมมุติว่าได้ติดตั้ง Virtual Box และ Oracle Linux แล้ว

เตรียมความพร้อมก่อนการติดตั้ง
RAM ทั้ง 2 เครื่องรวมกันควรเท่ากับหรือมากกว่า 9 GB
Disk ทั้ง 2 ควรแบ่งให้ local เครื่องละ 30GB ขึ้นไป
Prepare Network
1.เซต Network 3 ตัว
ตัวแรกเซตเป็น NAT


ตัวที่สองเซตเป็น Internal Network

ตัวที่สามเซตเป็น Host-only Adapter

2. เซต Host-only Network เพื่อใช้เป็น Public Network ของ RAC
  • Start VirtualBox จากเมนู.
  • เลือก "File > Preferences"
  • คลิก "Network" ตรงแถบด้านซ้ายแล้วเลือกแท็บ "Host-only Networks"
  • คลิก "Add host-only network (Ins)" ที่ปุ่ม + สีเขียวด้านขวา Network ชื่อ "VirtualBox Host-Only Ethernet Adapter" จะถูกสร้างขึ้นมา
คลิกขวาแล้วแก้ไขเราสามารถดูได้ว่า IP , Subnet ของ VirtualBox Host-only Network ถูกตั้งเป็นอะไรเราสามารถแก้ไขได้แต่ไม่ควรแก้ Subnet ให้ตรงกับ Subnet ที่เครื่องเราใช้จริง จากในตัวอย่างใช้ IP 192.168.172.1

3.เซต Network adapter ใน Linux
จากตัวอย่างเซตแบบนี้
  • hostname: kitti-rac1.localdomain
  • eth0: DHCP (Connect Automatically)
  • eth1: IP=172.16.172.101, Subnet=255.255.0.0, Gateway=0.0.0.0, DNS=<blank> Search=<blank> (Connect Automatically)
  • eth2: IP=192.168.172.101, Subnet=255.255.255.0, Gateway=<blank>, DNS=192.168.172.101,192.168.172.102 Search=localdomain (Connect Automatically)

4.แก้ไฟล์ /etc/hosts
127.0.0.1       localhost.localdomain   localhost
# Public
192.168.172.101   kitti-rac1.localdomain        kitti-rac1
192.168.172.102   kitti-rac2.localdomain        kitti-rac2
# Private
172.16.172.101   kitti-rac1-priv.localdomain   kitti-rac1-priv
172.16.172.102   kitti-rac2-priv.localdomain   kitti-rac2-priv
# Virtual
192.168.172.103   kitti-rac1-vip.localdomain    kitti-rac1-vip
192.168.172.104   kitti-rac2-vip.localdomain    kitti-rac2-vip
# SCAN
192.168.172.105   kitti-scan.localdomain   kitti-scan
192.168.172.106   kitti-scan.localdomain   kitti-scan
192.168.172.107   kitti-scan.localdomain   kitti-scan

5.ติดตั้ง dnsmasq เพื่อใช้ dns
# yum install dnsmasq
แก้ไฟล์ /etc/resolv.conf
search localdomain
nameserver 192.168.172.101
nameserver 192.168.172.102

*เพื่อป้องกัน /etc/resolv.conf ถูกเขียนทับโดย Network Manager เพราะเราเซต eth0 เป็น NAT เราจึงต้องทำการแก้ไฟล์ "/etc/sysconfig/network-scripts/ifcfg-eth0" โดยปรับ ONBOOT=no หลังจากนั้นลอง reboot เครื่อง

ลองสั่ง start service
# service dnsmasq stop
# service dnsmasq start

ลองสั่ง nslookup
# nslookup kitti-scan
Server: 192.168.172.1
Address: 192.168.172.1#53

Name: kitti-scan.localdomain
Address: 192.168.56.105
Name: kitti-scan.localdomain
Address: 192.168.56.106
Name: kitti-scan.localdomain
Address: 192.168.56.107

แก้ไฟล์ /etc/dnsmasq.conf โดยปรับ
local=/localdomain/

Prepare OS
1.แก้ไขไฟล์ "/etc/security/limits.d/90-nproc.conf" เพื่อแก้ปัญหา MOS Note [ID 1487773.1]
# แก้จาก
*          soft    nproc    1024

# เป็น
*           -       nproc    16384

2. Disable SElinux "/etc/selinux/config"
SELINUX=disabled

3.ปิดไฟวอ
service iptables stop
chkconfig iptables off

4.Disable Network Time Protocal (NTP) เพื่อเราจะได้ใช้ Oracle Cluster Time Synchronization Service (ctssd) เพื่อให้มันซิงค์วันที่และเวลาระหว่างทุกเครื่องใน RAC
service ntpd stop
chkconfig ntpd off

5.สร้าง Directories เพื่อเก็บ Software
mkdir -p  /u01/app/12.1.0.2/grid
mkdir -p /u01/app/oracle/product/12.1.0.2
chown -R oracle:oinstall /u01
chmod -R 775 /u01/

6.Login user เป็น oracle แล้วใส่ใน .bash_profile
# Oracle Settings
export TMP=/tmp
export TMPDIR=$TMP

export ORACLE_HOSTNAME=kitti-rac1.localdomain
export ORACLE_UNQNAME=KITTIRAC
export ORACLE_BASE=/u01/app/oracle
export GRID_HOME=/u01/app/12.1.0.2/grid
export ORACLE_HOME=$ORACLE_BASE/product/12.1.0.2
export ORACLE_SID=KITTIRAC1
export ORACLE_TERM=xterm
export BASE_PATH=/usr/sbin:$PATH
export PATH=$ORACLE_HOME/bin:$BASE_PATH

export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib
export CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib

7. Reboot เครื่อง 1 ทีพอเสร็จแล้วให้กด Devices > Install Guest Additions CD image...

8.เพิ่ม user oracle เข้าไปใน "vboxsf" group เพื่อให้มัน access เข้า shared drives ได้
# usermod -G vboxsf,dba oracle
# id oracle

uid=54321(oracle) gid=54321(oinstall) groups=54321(oinstall),54322(dba),54323(vboxsf)

9.สร้าง Shared Folder เพื่อสามารถเก็บไฟล์ต่างๆให้แชร์กันระหว่าง Host กับ Guest ได้โดยคลิกไปที่ Devices > Shared Folders Settings... คลิกสร้างทางด้านขวาแล้วเลือกให้เป็น Auto-mount กับ Make Permanent




Prepare Storage
1.สร้าง Shared Disks
ปิดเครื่องก่อน init 0
แล้วแอด harddisk เพิ่มเข้าไปตามต้องการโดยปรับให้เป็นแบบ Fixed Size

2.เข้าไปที่  File > Virtual Media Manager... แล้วปรับให้ disk ที่เพิ่มเข้ามาใหม่เป็นประเภท Shareable

3.เปิดเครื่อง kitti-rac1 ขึ้นมาแล้วเข้าไปที่ user root เพื่อ config disks
disks ปัจจุบันเราสามารถเห็นได้จาก 
ls /dev/sd*
/dev/sda  /dev/sda1  /dev/sda2  /dev/sdb  /dev/sdc  /dev/sdd

4.ใช้คำสั่ง fdisk เพื่อแบ่ง partition โดยในตัวอย่างจะแบ่งของ sdb จนถึง sdd

# fdisk /dev/sdb
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x54f59eed.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): n  
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-652, default 1): 
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-652, default 652): 
Using default value 652

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

5.ตั้งค่า UDEV rules
สำหรับการใช้ Oracle ASM เพื่อใช้ Disks มันต้องสามารถระบุ devices และพวกมันต้องมี ownership และ permissions ที่ถูกต้องในที่นี้เราจะใช้ UDEV rules

   5.1 แก้ไฟล์ถ้าไม่มีก็สร้าง /etc/scsi_id.config เพื่อ configure SCSI devices as trusted
         ใส่ไปตามนี้
          options=-g
   5.2 ดู SCSI_ID ของ shared disks ที่เราสร้างไว้
         # /sbin/scsi_id -g -u -d /dev/sdb
         1ATA_VBOX_HARDDISK_VBbd305c02-710a78b1
         # /sbin/scsi_id -g -u -d /dev/sdc
         1ATA_VBOX_HARDDISK_VB8db6505e-93acf98c
         # /sbin/scsi_id -g -u -d /dev/sdd
         1ATA_VBOX_HARDDISK_VBe47fab34-ff1b89f2
    5.3 เอาค่าที่ได้ไปใส่ในไฟล์ /etc/udev/rules.d/99-oracle-asmdevices.rules แล้วกำหนด owner กับ permissions
KERNEL=="sdb1", BUS=="scsi", PROGRAM=="/sbin/scsi_id -g -u -d /dev/$parent", RESULT=="1ATA_VBOX_HARDDISK_VBbd305c02-710a78b1",
  NAME="asm1", OWNER="oracle", GROUP="oinstall", MODE="0660"
KERNEL=="sdc1", BUS=="scsi", PROGRAM=="/sbin/scsi_id -g -u -d /dev/$parent", RESULT=="1ATA_VBOX_HARDDISK_VB8db6505e-93acf98c",
  NAME="asm2", OWNER="oracle", GROUP="oinstall", MODE="0660"
KERNEL=="sdd1", BUS=="scsi", PROGRAM=="/sbin/scsi_id -g -u -d /dev/$parent", RESULT=="1ATA_VBOX_HARDDISK_VBe47fab34-ff1b89f2",
  NAME="asm3", OWNER="oracle", GROUP="oinstall", MODE="0660"
    5.4 โหลด updated block device partition tables.
    # /sbin/partprobe /dev/sdb1
    # /sbin/partprobe /dev/sdc1
    # /sbin/partprobe /dev/sdd1
    5.5 เทส rules ว่าทำงานตามที่ต้องการไหม
    /sbin/udevadm test /block/sdb/sdb1
    /sbin/udevadm test /block/sdc/sdc1
    /sbin/udevadm test /block/sdd/sdd1
    5.6 Reload UDEV rules และ start UDEV
    # /sbin/udevadm control --reload-rules
    # /sbin/start_udev
    5.7 Disks ควรเห็นได้จากคำสั่งตามด้านล่างนี้ ถ้าเกิดไม่เห็นแสดงว่าเราปรับ UDEV ผิดต้องแก้ไขก่อน

Clone Server
1.ปิดเครื่อง kitti-rac1
เมื่ออยู่หน้า VirtualBox Manager ให้คลิกขวาที่เครื่องของเราแล้วเลือก Clone...

2.ตั้งชื่อใหม่จาก oel-rac1 เป็น oel-rac2 และติ๊กถูกที่ Reinitialize the MAC address of all network cards

3.เลือก Full Clone

4.เมื่อ Clone เสร็จก็เปิดเครื่อง oel-rac2 แล้วแก้ config ต่างๆโดยเซต Network ตามด้านล่าง
  • hostname: kitti-rac2.localdomain
  • eth0: DHCP (Connect Automatically)
  • eth1: IP=172.16.172.102, Subnet=255.255.0.0, Gateway=0.0.0.0, DNS=<blank> Search=<blank> (Connect Automatically)
  • eth2: IP=192.168.172.102, Subnet=255.255.255.0, Gateway=<blank>, DNS=192.168.172.101,192.168.172.102 Search=localdomain (Connect Automatically)
5.แก้ชื่อ Hostname ที่ไฟล์ /etc/sysconfig/network

NETWORKING=yes

HOSTNAME=ol6-121-rac2.localdomain



6.แก้ MAC Address ของ eth0 , eth1 , eth2 ให้ตรงกับ Network Adapter ของมัน

แก้ที่ไฟล์ /etc/sysconfig/network-scripts/ifcfg-eth0 , /etc/sysconfig/network-scripts/ifcfg-eth1 , /etc/sysconfig/network-scripts/ifcfg-eth2

ที่ "HWADDR=..."
โดยดูจาก
เช่น 
HWADDR=08:00:27:F1:66:6A

ทำให้ครบทั้ง 3 Adapter

*ตรวจสอบที่ /etc/sysconfig/network-scripts/ifcfg-eth0 ด้วยว่า ONBOOT=no หรือไม่ถ้าเป็น yes ให้ปรับเป็น no

7.แก้ /home/oracle/.bash_profile
export ORACLE_SID=KITTIRAC2
export ORACLE_HOSTNAME=kitti-rac2.localdomain

8.Restart kitti-rac2 server และ start kitti-rac1 ด้วย

9.ลอง ping ทดสอบดูว่าทั้ง public และ private ip สามารถใช้ได้หรือไม่
ping kitti-rac1
ping kitti-rac1-priv
ping kitti-rac2
ping kitti-rac2-priv

10.เช็ค SCAN ว่ายังสามารถ resolved ทั้งสอง node หรือไม่
# nslookup kitti-scan
Server:         192.168.172.101
Address:        192.168.172.101#53

Name:   kitti-scan.localdomain
Address: 192.168.172.107
Name:   kitti-scan.localdomain
Address: 192.168.172.105
Name:   kitti-scan.localdomain
Address: 192.168.172.106

*ตอนนี้อย่าพึ่ง ping virtual ip เพราะตอนนี้มันยังใช้ไม่ได้

11.ปิดเครื่อง kitti-rac2 แล้วทำการแอด shared disk เข้าไปโดยเลือก Add Harddisk แล้วเลือก Choose existing disk

12.เช็คที่เครื่อง kitti-rac2 โดยสั่ง ls -l /dev/asm* ถ้าไม่ขึ้นตามนี้ให้ลอง config udev rules ใหม่ตามวิธีก่อนหน้า (ตั้งแต่ OEL 6.3 ขึ้นไปน่าจะขึ้นหมดไม่มีปัญหา)
# ls -l /dev/asm*
brw-rw---- 1 oracle oinstall 8, 17 Apr  8 10:24 /dev/asm1
brw-rw---- 1 oracle oinstall 8, 33 Apr  8 10:24 /dev/asm2
brw-rw---- 1 oracle oinstall 8, 49 Apr  8 10:24 /dev/asm3

Install the Grid Infrastructure
1.เปิดเครื่องขึ้นมาทั้ง 2 เครื่องแล้วติดตั้ง rpm นี้ไว้ทั้ง 2 เครื่อง
# cd /media/sf_Oracle12c/grid/rpm
# rpm -Uvh cvuqdisk*

2.Login ไปที่ user oracle ของเครื่อง kitti-rac1 แล้วสั่ง
$ cd /media/sf_Oracle12c/grid
$ ./runInstaller

3.เลือก "Install and Configure Oracle Grid Infrastructure for a Cluster" แล้วคลิก Next

4.เลือก "Configure a Standard Cluster" แล้วคลิก Next

5.เลือก "Typical Installation" แล้วคลิก Next

6.ตั้งชื่อ SCAN ให้ตรงหลังจากนั้นคลิก Add...

7.ใส่ค่าลอง node kitti-rac2 ลงไป

8.คลิก "SSH Connectivity..." ใส่ password ของ oracle user อีกเครื่องนึงให้ถูกต้องจากนั้นกด Setup แล้วคลิก Next

9.เช็ค public และ private network ว่าถูกต้อง ถ้าหากมี interface ที่เป็น NAT อยู่ด้วยให้เลือกเป็น Do Not Use

10.ใส่ "/u01/app/12.1.0.2/grid" ลงไปใน Software Location แล้วเลือก Cluster Registry Storage Type เป็น Oracle Automatic Storage Management


11.ปรับ Redundancy เป็น "External" แล้วคลิก Change Discovery Path... ใส่ค่าเป็น "/dev/asm*" จะขึ้น disks available มาแสดง

12.เลือก default inventory directory แล้วคลิก Next

13.ถ้าเรามี root scripts ให้รันอัตโนมัติ แต่แนะนำให้ทำ Manual ดีกว่า คลิก Next

14.รอซักพักจน Prerequisite checks เสร็จถ้ามีปัญหาใดๆให้ลองกด "Fix & Check Again" ถ้าสามารถแก้ไขได้แล้วยังมีปัญหาอีกหากไม่มีผลกระทบอะไรสามารถกด Ignore All แล้วคลิก Next

15.ตรวจสอบ summary ให้เรียบร้อยหากไม่มีอะไรผิดพลาดสามารถคลิก Install เพื่อเริ่มการติดตั้งได้เลย

16.รอ...

17.รันสคริปต์ด้วย root ทั้ง 2 node

18.หลังจากรันสคริปต์หมดก็รออีกซักพักก็จะเสร็จสมบูรณ์

   Check status of the installation
# crsctl status res -t
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details       
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.DATA.dg
               ONLINE  ONLINE       kitti-rac1               STABLE
               ONLINE  ONLINE       kitti-rac2               STABLE
ora.LISTENER.lsnr
               ONLINE  ONLINE       kitti-rac1               STABLE
               ONLINE  ONLINE       kitti-rac2               STABLE
ora.asm
               ONLINE  ONLINE       kitti-rac1               Started,STABLE
               ONLINE  ONLINE       kitti-rac2               Started,STABLE
ora.net1.network
               ONLINE  ONLINE       kitti-rac1               STABLE
               ONLINE  ONLINE       kitti-rac2               STABLE
ora.ons
               ONLINE  ONLINE       kitti-rac1               STABLE
               ONLINE  ONLINE       kitti-rac2               STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
      1        ONLINE  ONLINE       kitti-rac2               STABLE
ora.LISTENER_SCAN2.lsnr
      1        ONLINE  ONLINE       kitti-rac1               STABLE
ora.LISTENER_SCAN3.lsnr
      1        ONLINE  ONLINE       kitti-rac1               STABLE
ora.MGMTLSNR
      1        ONLINE  ONLINE       kitti-rac1               169.254.199.72 172.1
                                                             6.172.101,STABLE
ora.cvu
      1        ONLINE  ONLINE       kitti-rac1               STABLE
ora.kitti-rac1.vip
      1        ONLINE  ONLINE       kitti-rac1               STABLE
ora.kitti-rac2.vip
      1        ONLINE  ONLINE       kitti-rac2               STABLE
ora.mgmtdb
      1        ONLINE  ONLINE       kitti-rac1               Open,STABLE
ora.oc4j
      1        ONLINE  ONLINE       kitti-rac1               STABLE
ora.scan1.vip
      1        ONLINE  ONLINE       kitti-rac2               STABLE
ora.scan2.vip
      1        ONLINE  ONLINE       kitti-rac1               STABLE
ora.scan3.vip
      1        ONLINE  ONLINE       kitti-rac1               STABLE
--------------------------------------------------------------------------------

Install the Database Software
1.เช็คให้แน่ใจว่าทั้ง 2 เครื่องเปิดอยู่

2.Login ไปที่ user oracle ของเครื่อง kitti-rac1 แล้วสั่ง
$ cd /media/sf_Oracle12c/database
$ ./runInstaller

3.เอาติ๊กถูกที่ Security Update ออกแล้วคลิก Next (จะมีข้อความเตือนให้คลิก OK)

4.ติ๊กเลือก Install database software only แล้วคลิก Next

5.ติ๊กเลือก Oracle Real Application Clusters database installation แล้วคลิก Next

6.ติ๊กเลือก nodes ที่เราต้องการทำเป็น RAC แล้วคลิก Next

7.เลือกภาษาที่ต้องการแล้วคลิก Next

8.ติ๊ก Enterprise Edition แล้วคลิก Next

9.ใส่ /u01/app/oracle เป็น Oracle Base และ /u01/app/oracle/product/12.1.0.2 เป็น Software Location
หลังจากนั้นคลิก Next

10.เลือก OS Group ที่ต้องการหลังจากนั้นคลิก Next

11.รอ prerequisite check จนเสร็จถ้าหากมีปัญหาใดๆให้ลองกด "Fix & Check Again" หรือติ๊ก "Ignore All" แล้วคลิก Next

12.ตรวจสอบ summary ให้เรียบร้อยหากไม่มีอะไรผิดพลาดสามารถคลิก Install เพื่อเริ่มการติดตั้งได้เลย


13.รอ...

14.รันสคริปต์ด้วย root ทั้ง 2 node
15.เสร็จสิ้น...

Create Database
1.เช็คให้แน่ใจว่าทั้ง 2 เครื่องเปิดอยู่

2.Login ไปที่ user oracle ของเครื่อง kitti-rac1 แล้วสั่ง
$ dbca

3.เลือก Create Database แล้วคลิก Next

4.เลือกโหมดการสร้างตามต้องการแล้วคลิก Next

5.รอ prerequisite check จนเสร็จถ้าหากมีปัญหาใดๆให้แก้ไขก่อนหรือจะ "Ignore All" แล้วคลิก Next

6.ตรวจสอบ summary ให้เรียบร้อยหากไม่มีอะไรผิดพลาดสามารถคลิก Install เพื่อเริ่มการติดตั้งได้เลย

7.รอ...

8.สร้างเสร็จแล้วถ้าอยากเปลี่ยนพาสเวิร์ดให้กด Password Management... หรือจะเปลี่ยนทีหลังก็ได้

Check the RAC status
$ srvctl config database -d KITTIRAC
Database unique name: KITTIRAC
Database name: KITTIRAC
Oracle home: /u01/app/oracle/product/12.1.0.2
Oracle user: oracle
Spfile: +DATA/KITTIRAC/PARAMETERFILE/spfile.288.876578023
Password file: +DATA/KITTIRAC/PASSWORD/pwdkittirac.276.876577021
Domain: 
Start options: open$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on Thu Apr 9 14:04:53 2015

Copyright (c) 1982, 2014, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Application Testing options

SQL> select inst_name from v$active_instances;

INST_NAME
--------------------------------------------------------------------------------
kitti-rac1.localdomain:KITTIRAC1
kitti-rac2.localdomain:KITTIRAC2
Stop options: immediate
Database role: PRIMARY
Management policy: AUTOMATIC
Server pools: 
Disk Groups: DATA
Mount point paths: 
Services: 
Type: RAC
Start concurrency: 
Stop concurrency: 
OSDBA group: dba
OSOPER group: 
Database instances: KITTIRAC1,KITTIRAC2
Configured nodes: kitti-rac1,kitti-rac2
Database is administrator managed

$ srvctl status database -d KITTIRAC
Instance KITTIRAC1 is running on node kitti-rac1

Instance KITTIRAC2 is running on node kitti-rac2

เช็ค v$active_instances เพื่อดูว่า instance ไหนรันอยู่


$ sqlplus / as sysdba

SQL*Plus: Release 12.1.0.2.0 Production on Thu Apr 9 14:04:53 2015

Copyright (c) 1982, 2014, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Application Testing options

SQL> select inst_name from v$active_instances;

INST_NAME
--------------------------------------------------------------------------------
kitti-rac1.localdomain:KITTIRAC1
kitti-rac2.localdomain:KITTIRAC2


ตัวอย่างบางส่วนศึกษามาจาก http://oracle-base.com/articles/12c/oracle-db-12cr1-rac-installation-on-oracle-linux-6-using-virtualbox.php

วันเสาร์ที่ 28 มีนาคม พ.ศ. 2558

สร้าง Job Scheduler ง่ายๆด้วย Oracle Scheduler

Oracle Scheduler มีประโยชน์ในการกำหนดงานให้ทำแบบอัตโนมัติตามเวลาหรือเหตุการณ์ที่เราได้ตั้งไว้
และมันยังสามารถตั้งค่าให้งานนึงรันต่อจากอีกงานนึงก็ได้ (Job chain) อีกทั้งยังประยุกต์ใช้ร่วมกับ Resource Manager เพื่อกำหนด Priorities ต่างๆได้อีกด้วย
เราสามารถสร้าง Job ให้รันงานได้หลายประเภทเช่น PLSQL_BLOCK , STORED_PROCEDURE , หรือ EXECUTABLE
โดย PLSQL_BLOCK คือ SQL statement , PL/SQL anonymous block
STORED_PROCEDURE คือ stored procedure ซึ่งสามารถเป็น pl/sql , java หรือ external procedure ที่เขียนด้วย C
EXECUTABLE คือชุด OS command , executable binary file , หรือ shell script หรือ batch file
โดยเมื่อเรากำหนดประเภทของมันแล้วเราต้องกำหนด Action ให้ตรงกันด้วย

ตัวอย่างการสร้าง Job อย่างง่ายด้วย DBMS_SCHEDULER
1. สร้าง table ไว้เก็บวันที่และเวลา

create table num (c1 date);

2. ปรับรูปแบบวันที่ให้ดูนาทีได้

alter session set nls_date_format='dd-mm-yy hh24:mi:ss';

3. สร้าง job ขึ้นมาโดยสั่งให้ Insert วันที่กับเวลาลงใน TIMES table โดยให้ทำทุกๆ 1 นาที

begin
    dbms_scheduler.create_job(
    job_name=>'savedate',
    job_type=>'plsql_block',
    job_action=>'insert into times values(sysdate);',
    start_date=>sysdate,
    repeat_interval=>'freq=minutely;interval=1',
    enabled=>true,
    auto_drop=>false);
end;
/

4. ลอง query ดู
select * from times;

C1
-----------------
28-03-15 22:48:57
28-03-15 22:49:57
28-03-15 22:50:57

5. เราสามารถยกเลิกและลบ JOB ของเราทิ้งได้ด้วย

exec dbms_scheduler.disable('savedate');

exec dbms_scheduler.drop_job('savedate');


เราสามารถสร้าง Program และ Schedule ขึ้นมาแล้วให้ JOB อื่นมาเรียก Program และ Schedule ของเราได้อีกหลายๆครั้ง เป็นการ Reuse Operation ได้โดยเรากำหนด Action ไว้ที่ Program และเวลาที่รันไว้ที่ Schedule แทน
ตัวอย่าง
1. สร้าง Program ขึ้นมาก่อน

begin
    dbms_scheduler.create_program(
    program_name=>'savedate',
    program_action=>'insert into times values(sysdate);',
    program_type=>'plsql_block',
    comments=>'Insert current date into the TIMES table',
    enabled=>true);
end;
/
NOTE : JOB และ PROGRAM แชร์ Namespace กันเราไม่สามารถสร้าง JOB และ PROGRAM มีชื่อเหมือนกันได้

2. สร้าง Schedule ขึ้นมาและกำหนดว่ารันทุก 3 นาที

begin
    dbms_scheduler.create_schedule(
    schedule_name=>'every_three_minute',
    start_date=>sysdate,
    repeat_interval=>'freq=minutely;interval=3',
    comments=>'Every 3 minutes');
end;
/

3. สร้าง JOB ขึ้นมาแล้วสั่งให้ใช้ Program กับ Schedule ที่มีอยู่

begin
    dbms_scheduler.create_job(
    job_name=>'increase_date',
    program_name=>'savedate',
    schedule_name=>'every_three_minute',
    enabled=>true,
    auto_drop=>false);
end;
/

4. ลอง query ดู

select * from times;
C1
-----------------
28-03-15 23:05:07
28-03-15 23:08:07
28-03-15 23:11:07
28-03-15 23:14:07


ตัวอย่างที่ 2 สร้าง job เพื่อทำ begin backup และ end backup (สร้างบน SYS หรือ SYSTEM) โดยให้รันวันละ 1 ครั้งตามเวลาที่กำหนด

begin
    dbms_scheduler.create_job(
    job_name=>'begin_backup',
    job_type=>'plsql_block',
    job_action=>'begin
    execute immediate ''alter database begin backup''; end;',
    start_date=>to_date('17-JUL-2017 17:28:00','DD-MON-YYYY HH24:MI:SS'),
    repeat_interval=>'freq=daily;interval=1',
    enabled=>true,
    auto_drop=>false);
end;
/

begin
    dbms_scheduler.create_job(
    job_name=>'end_backup',
    job_type=>'plsql_block',
    job_action=>'begin
    execute immediate ''alter database end backup''; end;',
    start_date=>to_date('17-JUL-2017 17:33:00','DD-MON-YYYY HH24:MI:SS'),
    repeat_interval=>'freq=daily;interval=1',
    enabled=>true,
    auto_drop=>false);
end;
/

ตัวอย่างบางส่วนใช้จากหนังสือ OCP Oracle 11g Administration II Exam Guide

วันจันทร์ที่ 24 พฤศจิกายน พ.ศ. 2557

ORA-14452: attempt to create, alter or drop an index on temporary table already in use

บางทีเราเห็นว่าไม่มีอะไรรันกับ object นั้นแล้วพอจะ drop มันก็ดันแจ้งว่ามีคนใช้อยู่
เราสามารถใช้ query ประมาณนี้เพื่อหา user ที่เป็นคน lock object นั้นอยู่แล้วค่อย kill ออกได้ครับ

select * from v$lock where id1 = (select object_id from dba_objects 
where owner = 'KITTI' and object_name = 'DEPARTMENTS');

วันอาทิตย์ที่ 23 พฤศจิกายน พ.ศ. 2557

ORA-06553: PLS-213: package STANDARD not accessible

Error นี้อาจเกิดขึ้นเพราะเรา Create Database ผ่าน command เองโดยไม่ได้ใช้ DBCA Tool
ซึ่งเราอาจ login ด้วย RMAN ไม่ได้และไม่สามารถ Query Data Dictionary Views ได้ด้วย
ซึ่งปัญหานี้ส่วนใหญ่มาจากที่เราไม่มี catalog database กับ procedures

ลองแก้ด้วยการรันสคริปต์ catalog.sql กับ catproc.sql ที่อยู่ใน $ORACLE_HOME/rdbms/admin/

SQL> @?/rdbms/admin/catalog.sql
...
...
...
...

 SQL> @?/rdbms/admin/catproc.sql
 ...
...
...
...

เมื่อรันเสร็จลอง Query Data Dictionary Views และลอง Connect เข้า RMAN ดูครับ

วันเสาร์ที่ 22 พฤศจิกายน พ.ศ. 2557

Resumable Space Allocation

Resumable space allocation จะช่วยให้ลดปัญหางานที่ต้องทำแล้วเกิดพื้นที่เก็บข้อมูลเต็ม แล้วลดเวลาที่ต้องรันใหม่ด้วยการระงับ (suspending) งานนั้นไว้ก่อนแทนที่จะยกเลิก (Terminate) งานนั้นเลย
ในขณะที่ Operation ถูก suspend DBA สามารถเพิ่ม disk space ไปที่ tablespace นั้นหรือเพิ่ม quota ให้กับ user นั้นๆได้ เมื่อเราเพิ่มเสร็จแล้ว Operation ที่ถูกระงับจะเริ่่มทำงานต่อไปโดยอัตโนมัติ


ทำความเข้าใจกับ Resumable Space Allocation
ถ้า statement ถูกระงับ transaction ที่เป็นเจ้าของ statement นั้นจะถูกระงับไปด้วย
เงื่อนไขตามนี้สามารถทำให้เกิดการ suspend แล้วใช้ resumable space allocation ได้
- Operation รันจน Permanent หรือ Temporary tablespace เต็ม
- Extents ถึงค่า Maximum ของ Tablespace นั้น
- User ใช้งานจนเกิน quota

เราสามารถควบคุมระยะเวลาที่ statement จะถูก suspend ค่า default คือ 2 ชั่วโมง หากไม่มีการเพิ่ม disk space หรือ quota เข้าไปมันจะเด้ง error message ขึ้นมาที่ user หรือ application นั้น

Command 4 ประเภทที่สามารถ resumable :
- SELECT : SELECT statements จะเข้าสู่การ resumable ได้ในกรณีเดียวคือรันจน temporary tablespace เต็มเมื่อเรามีการทำ sort operation เช่น ORDER BY , DISTINCT , หรือ UNION
- DML Commands : การ INSERT , UPDATE , DELETE สามารถทำให้ tablespace เต็มได้ ในกรณีของ DELETE อาจทำให้ undo tablespace เต็ม
- SQL*Loader : จาก command sqlldr เราสามารถเซต RESUMABLE parameter เป็น TRUE เราสามารถกำหนดชื่อของ resumable operation ด้วย RESUMABLE_NAME parameter ได้ด้วยตลอดจน resumable timeout ด้วย RESUMABLE_TIMEOUT parameter
- DDL Commands : ทุก DDL commands ที่ต้องใช้ disk space สำหรับ segments ใหม่หรือที่มีอยู่แล้วอาจ resumable ได้เช่น
   -- CREATE TABLE . . . AS SELECT (CTAS)
   -- CREATE INDEX
   -- ALTER TABLE . . . [MOVE | SPLIT] PARTITION
   -- ALTER INDEX . . . REBUILD
   -- ALTER INDEX . . . [REBUILD | SPLIT] PARTITION
   -- CREATE MATERIALIZED VIEW


การตั้งค่า Resumable Space Allocation
เราสามารถเปิดใช้งาน Resumable Space Allocation ได้ง่ายๆโดยเซตระดับ Instance ด้วย RESUMABLE_TIMEOUT initialization parameter หรือระดับ session ด้วย ALTER SESSION command
ถ้าเราเซต RESUMABLE_TIMEOUT ให้มีค่ามากกว่า 0 จะเป็นการเปิดใช้งาน Resumable Space Allocation โดยค่าที่เราเซตเข้าไปจะเป็นระยะเวลาที่ Operation จะถูก suspend ไว้และมันเป็ฯ dynamic parameter เราจึงสามารถเซตได้โดยไม่ต้องรีสตาร์ท
มีหน่วยเป็นวินาทีเ่ช่น
SQL> ALTER SYSTEM SET RESUMABLE_TIMEOUT = 7200; --เซตไว้ 2 ชั่วโมง

ถ้าเราเปิดใช้ระดับ system ทุก sessions จะสามารถใช้ Resumable Space Allocation ได้ ถ้าเราต้องการให้ users ไหนสามารถควบคุมการใช้งานได้มากขึ้นเราสามารถให้สิทธิ์ในการควบคุมเวลา suspend ของ user นั้นเองได้ด้วยการ
SQL> GRANT RESUMABLE TO users;

เมื่อ user ได้ RESUMABLE privilege แล้วจะสามารถเปิดใช้งาน resumable และตั้งเวลาเองได้ผ่าน ALTER SESSION command เช่น
SQL> ALTER SESSION ENABLE RESUMABLE;
SQL> ALTER SESSION ENABLE RESUMABLE TIMEOUT 10000;

เราสามารถดูข้อมูล resumable ได้ผ่าน data dictionary  DBA_RESUMABLE , USER_RESUMABLE เราสามารถเปิดใช้ได้ด้วยการเซต NAME มันลงไป
SQL> ALTER SESSION ENABLE RESUMABLE NAME 'Create Big Table';

SQL> select user_id,session_id,status,name,sql_text from dba_resumable;

USER_ID  SESSION_ID  STATUS    NAME                      SQL_TEXT
------------  -----------------  ------------    -------------------------  --------------------------------------------------
85                             124  NORMAL  Create Big Table      create table sale_history as select
                                                                                            * from sale_orders;

Session สามารถปิดการใช้งาน resumable ได้โดย
SQL> ALTER SESSION DISABLE RESUMABLE;


ประยุกต์ใช้กับ Trigger
เราสามารถสร้าง Trigger  AFTER SUSPEND system event เพื่อแจ้งเตือนทาง email ให้กับ User ที่เรา focus และ DBA รับทราบเช่น

CREATE OR REPLACE TRIGGER resumable_notify
    AFTER SUSPEND ON DATABASE
DECLARE
   -- ประกาศตัวแปรถ้าต้องการ
BEGIN
   DBMS_RESUMABLE.SPACE_ERROR_INFO( . . . ); --เช็คข้อมูล user id , ใน DBA_RESUMABLEจะ return ค่าเป็น boolean ถ้าไม่สามารถหาข้อมูล space error ได้จะ return FALSE
   IF object_type = 'TABLE' and object_owner = 'HR' THEN
      DBMS_RESUMABLE.SET_TIMEOUT(7200);
      UTL_MAIL.SEND('orakitti@example.com', . . .);
   ELSE -- ยกเลิก statement อื่นที่ถูก suspend ไว้
      DBMS_RESUMABLE.ABORT( . . . );
   END IF;
END;


ตัวอย่างการใช้งาน
1. Grant resumable ให้ HR ก่อน



















2. สร้าง Tablespace มี 1 datafile ขนาด 10M ขึ้นมาเพื่อทดสอบ












3. Connect เข้า HR แล้วลองวนลูปสร้าง table เพื่อให้ tablespace เต็ม

4. Enable RESUMABLE และตั้งเวลาไว้ 3600 วินาที (1 ชั่ืวโมง)













5. ลองสร้างเพิ่มอีก Table นึงจะดูเหมือนว่ามันแฮ้งค์และมีข้อมูลขึ้นมาใน Alert Log ด้วย














Sat Nov 22 23:35:02 2014
statement in resumable session 'User HR(85), Session 520, Instance 1' was suspended due to
    ORA-01658: unable to create INITIAL extent for segment in tablespace KITTI_TBS
มันจะขึ้นใน EM ตรง Alert section ด้วย


6. จาก Admin user เราจะ Query  DBA_RESUMABLE เพื่อดูข้อมูลเกี่ยวกับ session ที่ถูก suspend











7. DBA ได้เพิ่ม datafile เข้าไปที่ tablespace KITTI_TBS อีก 1 ไฟล์
















เมื่อเพิ่มเข้าไปเสร็จแล้ว user HR สามารถทำ Operation ต่อได้โดยอัตโนมัติ ในที่นี้คือ Create Table
















และ Alert Log ก็แจ้งข้อความว่า Statement ได้ถูก resume แล้ว
Sat Nov 22 23:49:49 2014
statement in resumable session 'User HR(85), Session 520, Instance 1' was resumed


8. Query DBA_RESUMABLE อีกครั้งเพื่อยืนยันว่า Operation resumable แล้ว












** ถ้ามี session ถูก suspend จะมีข้อมูลขึ้นมาใน V$SESSION_WAIT ที่คอลัมน์ EVENT ว่า "statement suspended, wait error to be cleared"

เราควรแจ้งเตือน User ด้วยวิธีการใดๆก็ได้ (เช่น Trigger ส่งอีเมล) เพื่อให้ User เข้าใจว่าเกิดเหตุการ Suspend ขึ้น


Ref : OCP Oracle 11g Administration II Exam Guide