Patch Database ที่มี Data Guard มีวิธีการอย่างไร
กาลครั้งหนึ่งมิชิเกียงได้รับสาสน์ให้ patch Data Guard
สวัสดีอีกครั้งค่ะ เกียงนะคะ ตำแหน่ง Database Administrator อยู่ที่บริษัท Sirisoft Blog ที่แล้ว เราได้พูดถึง task เพิ่ม IP ให้ Exadata ไปเนอะ คราวนี้เราจะกล่าวถึงอีกหนึ่งงานของ DBA ที่มีความสำคัญไม่น้อย นั่นคือการ hardening ฐานข้อมูลนั่นเอง!!
นอกเหนือจากการปรับค่า parameter ให้เป็นไปตามข้อกำหนดก็มี patch database ให้เป็นเวอร์ชันล่าสุดค่ะ เผอิญว่าคราวนี้ database ที่ว่ามี Data Guard อยู่ตัวหนึ่ง เลยไม่ได้ patch คราวเดียวจบเหมือน single instance นึกดูตอนนั้นก็สนุกดี เลยอยากนำวิธีที่ใช้มาเล่าสู่กันฟังค่ะ o(*°▽°*)oo(*°▽°*)o
อารัมภบท
อะไรคือการ Hardening?
Hardening เป็นหนึ่งในวิธีเสริมสร้างความปลอดภัยให้กับระบบงานของเรา นอกจากเป็นการอุดช่องโหว่ (vulnerability) แล้ว ยังช่วยให้ประสิทธิภาพองค์รวมของระบบดีขึ้น พอความเสี่ยงลด ความมั่นใจในระบบของผู้ใช้งานและผู้ดูแลระบบจะก็ตามมาค่ะ โดยความเร่งด่วนและความจำเป็นก็สุดแล้วแต่ Service Level Agreement และ Security Policy ที่ยอมรับร่วมกันเลย
ตัวอย่างข้อปฏิบัติสำหรับการ hardening database ค่ะ
- อัปเกรด package ที่ใช้ให้เป็นเวอร์ชันที่เหมาะสม
- จำกัดสิทธิ์การเข้าถึงผู้ใช้งาน
- นโยบายเปลี่ยนรหัสผ่านทุก x เดือน โดยรหัสต้องมีความซับซ้อน
- เปิดใช้งาน audit ในระดับที่ยอมรับร่วมกัน
- ติดตั้ง patch เพื่ออุดช่องโหว่หรือแก้ bug ที่พบเจอในเวอร์ชันก่อน ๆ ที่อาจกระทบระบบ หรือเพื่อตัดไฟต้นลม ヾ(•ω•`)oヾ(•ω•`)o
ทำความรู้จัก Data Guard อย่างคร่าว
Data Guard (DG) เป็นหนึ่งใน High Availability (HA) Solution
นอกเหนือจาก Primary Database ก็จะมี Standby อีกอย่างน้อยหนึ่งตัวเป็น Disaster recovery (DR) เอาไว้เผื่อกู้คืนข้อมูลหากเกิดเหตุการณ์ไม่คาดคิดขึ้นกับ Primary database และเมื่อถึงคราวจำเป็นก็สามารถทำการ switchover หรือ failover ได้
Switchover — สลับบทบาทระหว่าง primary กับ standby
Failover — promote standby ขึ้นมาเป็น primary เมื่อ primary เดิมใช้งานไม่ได้อีก
- โดยสังเขป Primary จะมีหน้าที่ส่งข้อมูลไปยัง Standby ที่ส่วนมากจะอยู่คนละ Site
- ฝั่ง Standby ก็จะคอย apply log เรื่อย ๆ เพื่อให้ข้อมูลทั้งสองฝั่ง sync กันที่สุดค่ะ
อธิบาย environment ที่เราเอามาทดสอบ logic
- DC ของเราชื่อ mck_dc มี DB เวอร์ชัน 19.16 อยู่หนึ่งตัว — เป็น primary ชื่อ orcldc
- DR ของเราชื่อ mck_dr มี DB เวอร์ชัน 19.16 อยู่สองตัว ตัวหนึ่งเป็น physical standby ชื่อ orcldr อีกตัวเป็น single instance ชื่อ orcltest
Standby database จะมี 3 ประเภทหลัก ๆ ค่ะ
Physical Standby — เป็นแฝดของ primary แบบทุกระเบียบ เวลา apply log จะ apply redo ประเภทนี้จะเปิด DB แบบ read-only และเป็น real time query feature
Logical Standby — ตอนสร้างจะมีโครงเหมือน primary ทุกระเบียบ แต่สามารถแก้ไขให้โครงสร้างต่างออกไปได้ เวลา apply log จะเป็นการ execute SQL Statements, DB จึงเปิดแบบ read-write
Snapshot Standby — ประเภทนี้จะไม่ apply redo ที่รับมาจาก primary จนกว่าจะมีการแปลงกลับเป็น physical standby เหมาะกับเอาไว้ใช้ทดสอบระบบก่อนใช้จริงค่ะ
เราได้ลองทดสอบอยู่สองวิธีคือ ได้แก่…
- Simplicity is the best | วิธีเรียบง่าย
- cancel sync ระหว่าง primary กับ standby ชั่วคราว
- apply patch ที่ primary
- รัน post-patch ตามท้าย
- พอเรียบร้อยทุกขั้นตอนก็ sync คืน
2. Downtime minimization | ประหยัด downtime
- patch ที่ DR โดยไม่รัน post-patch
- switchover ให้ DB ที่ DR กลายเป็น primary
- patch DC site
- รัน post-patch ที่ DR
- [optional] จะ switchover กลับหรือไม่ก็ได้
หากสามารถรับ downtime ที่มากหน่อยได้ วิธีแรกก็เป็นตัวเลือกที่ไม่เลวเลยค่ะ เพราะการดำเนินการไม่ซับซ้อน แต่ถ้าอยากลด downtime หรืออยากทดสอบย้ายแอปพลิเคชันไปต่อที่ DR วิธีที่สองก็เป็นอีกตัวเลือกที่น่าสนใจและท้าทายมากยิ่งขึ้น ╰(*°▽°*)╯╰(*°▽°*)╯
Prerequisite
เวอร์ชันของ OPatch ต้องสัมพันธ์กับ patch ที่จะ apply
OPatch — เครื่องมือที่เอาไว้ apply & rollback patches
Patch — การ upgrade ฟีเจอร์เพื่ออัปเดต, ซ่อมแซมปัญหา, แก้ไข bug, หรือเพิ่มความปลอดภัยให้กับระบบ
- ตัวอย่างการโหลด patch DB RU เวอร์ชัน 19.18 จาก Oracle Support
- แวะอ่าน README
- เลื่อนไปที่ section OPatch Utility จากภาพจะเห็นว่า OPatch ควรเป็นเวอร์ชัน 12.2.0.34 เป็นต้นไป
- ตรวจสอบเวอร์ชันของ OPatch ได้จากคำสั่งนี้
cd $ORACLE_HOME/OPatch
./opatch version
- จากภาพ จะเห็นว่าเวอร์ชันของเราใหม่กว่า 12.2.0.1.34 แล้ว แต่หากเวอร์ชันเก่ากว่า requirement และจำเป็นต้องอัปเกรด สามารถโหลด OPatch มาลงใหม่ได้ตามภาพด้านล่างค่ะ
ก่อนจะอัปเกรดเวอร์ชันให้ OPatch เราแนะนำให้ backup $ORACLE_HOME/OPatch
เวอร์ชันเดิมไว้เผื่อ rollback นะคะ พอ backup แล้วก็ unzip เวอร์ชันใหม่ได้เลย พอรัน opatch version
อีกครั้งก็จะเห็นเป็นเวอร์ชันล่าสุดค่ะ (★‿★)(★‿★)
#backup the previous version of OPatch
tar -cvf oracle_home_opatch_$(date +%Y-%m-%d).tar $ORACLE_HOME/OPatch
#Unzip the newer version
cd $ORACLE_HOME
unzip -oq "PATH_TO_FILE/p6880880_190000_Linux-x86-64.zip"
cd $ORACLE_HOME/OPatch
./opatch version
เริ่ม Patch แบบแรกกันเลย
Note: ก่อน patch ครั้งนี้ DB ทั้งที่ DC และ DR ของเราเป็นเวอร์ชัน 19.16
Simplicity is the best | วิธีเรียบง่าย
ณ DR Site — ตรวจสอบให้แน่ใจว่า OPatch version เหมาะสม
- Cancel sync กับ DC
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
2. ปิด Listener ทุกตัว
Listener — โปรเซสหนึ่งที่เป็นตัวกลางระหว่างผู้ใช้งาน (client) และ DB คอยรับ connection request มาและบริหารจัดการ network traffic
#ex. lsnrctl stop LISTENER_DG_DR
lsnrctl stop [LISTENER_NAME]
3. ปิด database และ exit ออกจาก session
SHUTDOWN IMMEDIATE;
EXIT
4. Backup ORACLE_HOME
ไว้เผื่อ rollback
cd $ORACLE_HOME
tar -cvf oracle_home_bak_$(date +%Y-%m-%d).tar $ORACLE_HOME
5. Apply Patch ในที่นี้จะเป็น RU Patch เวอร์ชัน 19.18
#Apply RU Patch
#change into preferred directory or make a new directory if needed
#mkdir /u01/software
cd /u01/software/
unzip -oq "PATH_TO_PATCH_FILE/p34765931_190000_Linux-x86-64.zip"
cd "/u01/software/34765931/"
export PATH=$ORACLE_HOME/OPatch:$PATH
#perform prerequisite check
opatch prereq CheckConflictAgainstOHWithDetail -ph ./
#apply the patch
opatch apply -silent
หากสำเร็จ ผลสุดท้ายจะเป็นประมาณภาพด้านล่างค่ะ
Reminder: เนื่องจาก DB ที่ DR ของเราเป็นตัว standby อยากจะเก็บไว้เผื่อทำ disaster recovery เท่านั้น ตอนเราเปิดขึ้นมาเลยจะเปิดแค่ mount หรือ read-only ค่ะ
หากมี patch อื่น ๆ ที่ต้องการ apply เพิ่มก็สามารถทำวิธีการเดิมได้เลย
#Apply OJVM Patch
cd /u01/software/
unzip -oq "PATH_TO_PATCH_FILE/p34786990_190000_Linux-x86-64.zip"
cd "/u01/software/34786990/"
export PATH=$ORACLE_HOME/OPatch:$PATH
#perform prerequisite check
opatch prereq CheckConflictAgainstOHWithDetail -ph ./
#apply the patch
opatch apply -silent
ณ DC Site — เช็คให้แน่ใจว่า OPatch tools เป็นเวอร์ชันที่สัมพันธ์กับ Patch ที่จะ Apply
6. ปิด Listener ทุกตัว
#ex. lsnrctl stop LISTENER_DG_DC
lsnrctl stop [LISTENER_NAME]
7. ปิด database และ exit ออกจาก session
SHUTDOWN IMMEDIATE;
EXIT
8. Backup ORACLE_HOME
ไว้เผื่อ rollback
cd $ORACLE_HOME
tar -cvf oracle_home_bak_$(date +%Y-%m-%d).tar $ORACLE_HOME
9. Apply Patch ในที่นี้จะเป็น RU Patch เวอร์ชัน 19.18
#Apply RU Patch
#change into preferred directory or make a new directory if needed
#mkdir /u01/software
cd /u01/software/
unzip -oq "PATH_TO_PATCH_FILE/p34765931_190000_Linux-x86-64.zip"
cd "/u01/software/34765931/"
export PATH=$ORACLE_HOME/OPatch:$PATH
#perform prerequisite check
opatch prereq CheckConflictAgainstOHWithDetail -ph ./
#apply the patch
opatch apply -silent
10. เปิด listener กลับคืนมา
#ex. lsnrctl start LISTENER_DG_DC
lsnrctl start [LISTENER_NAME]
11. เปิด database
12. เช็ค patch ที่ apply ใน ORACLE_HOME
Cd $ORACLE_HOME/bin
opatch lsinventory
อาจจะยาวเฟื้อยหน่อย แต่ผลที่ได้คือจะเห็นรายการ patch ค่ะ
13. รัน post-patch command
cd $ORACLE_HOME/OPatch
./datapatch -verbose
Datapatch — เครื่องมือ post-patch ที่ perform SQL หรือ PL/SQL Actions โดยอัตโนมัติเพื่ออัปเดตความเปลี่ยนแปลงให้กับ data dictionary
Data dictionary — รายการที่เก็บข้อมูล/รายละเอียดต่าง ๆ ของ database เช่นข้อมูล relation ระหว่างเทเบิล ขนาดของ field ฯลฯ
14. เช็คเวอร์ชันใน DB จะเห็นว่าอัปเดตจาก 19.16 เป็น 19.18 แล้ว
SELECT TO_CHAR(ACTION_TIME, 'YYYY-MM-DD HH24:MI') AS ACTION_TIME,ACTION,STATUS,
DESCRIPTION,PATCH_ID
FROM SYS.DBA_REGISTRY_SQLPATCH
ORDER BY ACTION_TIME;
cd $ORACLE_HOME/bin
opatch lspatches
ณ DR Site
15. Sync Primary-Standby
--Sync
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
--Check log applied time
SELECT SEQUENCE#,TO_CHAR(FIRST_TIME,'DD-MON-YYYY HH24:MI:SS') "LOG APPLIED TIME"
FROM V$LOG_HISTORY
WHERE FIRST_TIME=(SELECT MAX(FIRST_TIME) FROM V$LOG_HISTORY);
เช็คกับทาง DC ว่า log applied ตรงกันก็เป็นอันเรียบร้อย
หากมี Patch อื่น ๆ ที่ต้องการ Apply อีกก็ทำซ้ำข้อที่ 6–15 ได้เลยค่ะ ในที่นี้เรา Apply OJVM patch อีกตัว ผลลัพธ์สุดท้ายจะเป็นแบบนี้ทั้งข้าง DC และ DR ค่ะ
ลอง Patch แบบ Switch over ดูบ้าง o(* ̄▽ ̄*)ブ
Downtime minimization | ประหยัด downtime
- [DR — Standby] Patch DR สามารถทำตามข้อ 1–7 ของการ patch แบบแรกได้เลย
- [DC — Primary] Switchover ไป DR
หากมีการ configure Data Guard Broker ไว้ก็สั่งแบบนี้ได้เลยค่ะ
dgmgrl user/password
SWITCHOVER TO DESTINATION_DB_NAME
หากไม่มี สามารถใช้คำสั่งนี้แทนได้ค่ะ
ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY WITH SESSION SHUTDOWN;
3. [DR — Primary] Switch DR ขึ้นเป็น Primary
--Switch to Primary
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
--Restart
SHUTDOWN IMMEDIATE;
STARTUP;
4. [DC — Standby] Exit from SQL*Plus และปิด listener ทั้งหมด
#ex. lsnrctl stop LISTENER_DG_DC
lsnrctl stop [LISTENER_NAME]
Backup ORACLE_HOME
ไว้เผื่อ rollback
cd $ORACLE_HOME
tar -cvf oracle_home_bak_$(date +%Y-%m-%d).tar $ORACLE_HOME
Apply Patch ตัวแรก ในที่นี้จะเป็น RU Patch เวอร์ชัน 19.18
#Apply RU Patch
#change into preferred directory or make a new directory if needed
#mkdir /u01/software
cd /u01/software/
unzip -oq "PATH_TO_PATCH_FILE/p34765931_190000_Linux-x86-64.zip"
cd "/u01/software/34765931/"
export PATH=$ORACLE_HOME/OPatch:$PATH
#perform prerequisite check
opatch prereq CheckConflictAgainstOHWithDetail -ph ./
#apply the patch
opatch apply -silent
เปิด listener
#ex. lsnrctl start LISTENER_DG_DC
lsnrctl start [LISTENER_NAME]
เปิด database ขึ้นมาเป็น standby
STARTUP NOMOUNT;
ALTER DATABASE MOUNT STANDBY DATABASE;
ถึงตรงนี้สามารถทดสอบ Sync กับ DR — Primary ได้ค่ะ
--Check switchover status, there should be a gap between both side's logs
SELECT SWITCHOVER_STATUS FROM V$DATABASE;
--View log applied sequence before syncing
SELECT SEQUENCE# ,TO_CHAR(FIRST_TIME,'DD-MON-YYYY HH24:MI:SS') "LOG APPLIED TIME"
FROM V$LOG_HISTORY
WHERE FIRST_TIME=(SELECT MAX(FIRST_TIME) FROM V$LOG_HISTORY);
--Sync
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
--View log applied after syncing
SELECT SEQUENCE# ,TO_CHAR(FIRST_TIME,'DD-MON-YYYY HH24:MI:SS') "LOG APPLIED TIME"
FROM V$LOG_HISTORY
WHERE FIRST_TIME=(SELECT MAX(FIRST_TIME) FROM V$LOG_HISTORY);
5. [DR — Primary] รัน post-patch command
cd $ORACLE_HOME/OPatch
./datapatch -verbose
หลังจากนั้นก็ switchover ให้ DC เป็น Primary เหมือนเดิมก็เป็นอันจบค่ะ พวกโฟลเดอร์ทั้งหลายที่ unzip ออกมาที่ /u01/software
หรือไฟล์ซิปที่ backup OPatch และ $ORACLE_HOME
ก็สามารถลบได้ถ้าทดสอบแล้วไม่มีปัญหาอะไรให้ต้อง rollback
--With DG Broker
dgmgrl user/password
SWITCHOVER TO DESTINATION_DB_NAME
--Without DG Broker
---At DR
ALTER DATABASE COMMIT TO SWITCHOVER TO PHYSICAL STANDBY WITH SESSION SHUTDOWN;
SHUTDOWN IMMEDIATE;
STARTUP NOMOUNT;
ALTER DATABASE MOUNT STANDBY DATABASE;
---At DC
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
SHUTDOWN IMMEDIATE;
STARTUP;
---At DR
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
หากต้อง rollback ก็กลับไปที่โฟลเดอร์ที่พวกเรารัน opatch apply
แล้วสั่ง opatch rollback
ได้ค่ะ
#rollback OJVM Patch
cd "/u01/software/34786990/"
opatch rollback -id 34786990 -silent
#rollback RU Patch
cd "/u01/software/34765931/"
opatch rollback -id 34765931 -silent
— แต่เนื่องจากของเรามี database UAT อีกเครื่องที่ DR และด้วยอะไรหลาย ๆ อย่างทำให้ไม่สะดวก apply patch ที่ DR เราจึง switchover กลับไป DC แล้วรัน data patch ที่นั่นแทนค่ะ
[DC — Primary] หากต้องการ apply patch เพิ่มก็ทำซ้ำข้อที่ 2–5 ได้เลยค่ะ
ผลลัพธ์สุดท้ายของเราที่ Patch 2 ตัว (RE & OJVM) จะออกมาหน้าตาแบบนี้