วันจันทร์ที่ 13 กรกฎาคม พ.ศ. 2552

เปิด firewall policy อย่างไรกับ Oracle RAC


connect โดยใช้ VIP แล้ว
เวลาที่ cluster ตอบกลับ มันจะใช้ Public IP หรือ VIP ตอบกลับมาครับ เพราะน้องเขาต้องไปเปิด โพรีซีของพวกไฟร์วอลนะครั
บ

นั่นเป็นคำถามที่ คนทำ Oracle RAC DBA อาจจะสงสับว่า ความจริงเป็นอย่างไร... แน่นอนถ้าเรา install Oracle RAC โดยที่ไม่ได้ มีการปรับปรุงไรเลย
นั่นเป็นสิ่งที่ผิดจริงหรือ ไม่

ลอง lsnrctl services แล้วลองดูว่า เห็นอะไร

$ lsnrctl services...Service "service1" has 2 instance(s).
Instance "db1", status READY, has 1 handler(s) for this service...
Handler(s):"DEDICATED" established:2 refused:0 state:ready
REMOTE SERVER(ADDRESS=(PROTOCOL=TCP)(HOST=rac01)(PORT=1521))
Instance "db2", status READY, has 2 handler(s) for this service...Handler(s):"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER(ADDRESS=(PROTOCOL=TCP)(HOST=rac02)(PORT=1521))
"DEDICATED" established:8316 refused:0 state:readyLOCAL SERVER

นี่คือ default ที่ install เรียบร้อย เมื่อลอง TCPDUMP เพื่อจำ packets จากคำถามข้างบน
จะเห็นว่าตอนแรกนั้น client ติดต่อที่ VIP จริงแต่พอใช้งานไม่ใช่ แล้วดันไปใช้ที่ Public IP

client -> rac01-vip:1521..
client -> rac01:1521.
.
.


อย่างนี้ FailOver=ON ก็ไม่โอเคแน่นอน เพราะมันไม่ได้ใช้ VIP ดังนั้น เมื่อ node down ย่อมมีปัญหา (Firewall ต้องเปิดทั้ง VIP + Public IP)

ถ้า ศึกษาจาก Expert จะรู้ว่า client ต้องติดต่อ RAC Database ด้วย VIP ส่วนของ RAC servers เองต้อง register listener ที่ VIP ไม่ใช่ Public IP (metalink: มองว่าการ register listener ด้วย Public IP เป็นบัก จากการใช้ netca และ oracle tools ตอนสร้าง Listener)

กลับมาเรื่องของเรา ผมได้แก้ไขเกี่ยวกับ Listener อย่างคร่าวๆ เพื่อให้ register listener กับ VIP
-> listener.ora

rac01:
LISTENER_rac01 =
(DESCRIPTION_LIST =
(DESCRIPTION =(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac01-vip)(PORT = 1521)(IP = FIRST)))
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac01)(PORT = 1521)(IP = FIRST))))
)

rac02:
LISTENER_rac02 =
(DESCRIPTION_LIST =
(DESCRIPTION =(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac02-vip)(PORT = 1521)(IP = FIRST)))
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac02)(PORT = 1521)(IP = FIRST)))
))

-> tnsnames.ora on both nodes

LISTENERS_DB =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac01-vip)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac02-vip)(PORT = 1521))
)

LISTENERS_rac01 =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac01-vip)(PORT = 1521))
)

LISTENERS_rac02 =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac02-vip)(PORT = 1521))
)

-> DATABASE


rac01:

SQL> show parameter listener

NAME TYPE VALUE
-----------------------------------------------------------------
local_listener string LISTENERS_rac01
remote_listener string LISTENERS_DB

rac02:
SQL> show parameter listener

NAME TYPE VALUE
-----------------------------------------------------------------
local_listener string LISTENERS_rac02
remote_listener string LISTENERS_DB

จากนั้นเช็ค lsnrctl services
$ lsnrctl services
.
.
Service "service1" has 2 instance(s).
Instance "db1", status READY, has 1 handler(s) for this service...
Handler(s):"DEDICATED" established:2 refused:0 state:ready
REMOTE SERVER
(ADDRESS=(PROTOCOL=TCP)(HOST=rac01-vip)(PORT=1521))
Instance "db2", status READY, has 2 handler(s) for this service...Handler(s):"DEDICATED" established:0 refused:0 state:ready
REMOTE SERVER(ADDRESS=(PROTOCOL=TCP)(HOST=rac02-vip)(PORT=1521))
"DEDICATED" established:8316 refused:0 state:readyLOCAL SERVER


โอเค และทดสอบอีกครั้งด้วย TCPDUMP
client -> rac01-vip:1521..
client -> rac01-vip:1521.
.
.

ซึ่งตอนนี้ไม่เห็น Packets ที่ใช้ Public IP อีกแล้ว(งั้นเปิด firewall ที่ VIP เป็นอันพอ)...
นี่เป็นสิ่งที่ Oracle RAC DBA เรียนรู้และพัฒนาไอเดีย ;)




วันอังคารที่ 12 พฤษภาคม พ.ศ. 2552

จำนวน datafile ที่สามารถสร้างได้ บน Oracle ดาต้าเบส

ผู้ดูแลจะไม่พบปัญหา จนต้องตอบคำถามเกี่ยวกับจำนวน datafile บนดาต้าเบสที่ไม่ใหญ่มากนัก
แต่หากดาต้าเบสมีขนาดใหญ่ จนต้องใช้จำนวน tablespace มากๆ มันเริ่มจะมีคำถามกลับมาที่จำนวนของ datafile ที่จะสร้างได้ในดาต้าเบส

ผู้ดูแลดาต้าเบสสามารถที่จะหาจำนวนของ datafile ที่จะสามารถสร้างบนดาต้าเบส ได้จาก DB_FILES พารามิเตอร์

SQL> show parameter db_files

NAME TYPE VALUE
----------------------
db_files integer 200
จากตัวอย่าง สามารถสร้าง datafile ได้ที่ 200 ไฟล์
แต่ทั้งนี้ต้องขึ้นกัน Operation System (การจำกัดจำนวนไฟล์บน OS) ด้วย... ซึ่งจะเจอได้น้อยมาก

หากมีการสร้าง datafile ที่มากกว่าค่า db_files พารามิเตอร์ แน่นอนจะทำให้ผู้ดูแลรู้จัก ORA Error มากขึ้นอีกตัว

SQL> create tablespace a01 datafile '+DATA1' size 20M;
create tablespace a01 datafile '+DATA1' size 20M
*
ERROR at line 1:
ORA-00059: maximum number of DB_FILES exceeded
อย่างไรก็ตาม ผู้ดูแลสามารถที่จะเพิ่มค่า DB_FILES พารามิเตอร์
แต่ต้อง restart ดาต้าเบส...
ในเคสที่ใช้ Oracle RAC ผู้ดูแลต้อง shutdown ทุก node (shutdown ดาต้าเบส นั่นเอง... ไม่สามารถ restart ทีละnode)

ค่า db_files เท่าไหร่... ถึงจะเป็นค่าที่เหมาะสม
นั่นเป็นสิ่งที่ผู้ดูแลต้องคิดและตอบโจทย์ เพราะมันผูกกับการจำกัดจำนวนไฟล์บน OS... แล้วยังใช้ SGA memory ในการเก็บข้อมูล datafile ด้วย

หลายคนที่ใช้ Oracle ดาต้าเบส คงมีคำถามว่า... แล้ว MAXDATAFILES บน controlfile ??? ...ยังมีผลเกี่ยวข้องหรือไม่
แน่นอน! ถ้าคุณใช้ Oracle 8i หรือสูงกว่า ค่า MAXDATAFILES บน controlfile จะการขยายโดยอัตโนมัติ... เมื่อมีการเพิ่มจำนวน datafile เกินค่า MAXDATAFILES แต่น้อยกว่าหรือเท่ากับค่า db_files (metalink: 331067.1)

ตัวอย่างการเพิ่ม db_files พารามิเตอร์ (เมื่อใช้ spfile)
SQL> show parameter db_files

NAME TYPE VALUE
----------------------
db_files integer 200

SQL> alter system set set db_files=500 scope=spfile;

SQL> shutdown immediate

SQL> startup

SQL> show parameter db_files

NAME TYPE VALUE
----------------------
db_files integer 500
การเปลี่ยนค่า db_files ไม่ใช่ปัญหา ถ้าระบบสามารถหยุดการใช้งาน
สิ่งที่ยากยิ่งกว่า คือการกำหนดค่า ว่าในเวลาหนึ่งปี หรือสองปี ต้องใช้จำนวน datafile เท่าไหร่

วันอังคารที่ 5 พฤษภาคม พ.ศ. 2552

การลดขนาด (oracle) database segment ออนไลน์

ตั้งแต่ oracle 10g เราสามารถออนไลน์ลดขนาด(shrink) segment เพื่อให้ได้พื้นที่ว่าง ส่งผลให้เกิดประสิทธิภาพกับการเก็บข้อมูล พร้อมกันนี้ยังช่วยลด High Water Mark (HWM)
อย่างไรก็ตามวิธีนี้ใช้ได้กับ tablespace ที่เป็น Locally Manage และ Automatic Segment Space Management (ASSM)

การลดขนาด(shrink) segment สามารถทำได้ทั้ง TABLE และ INDEX แต่อย่างไรก็ตามเราต้อง enable row movement บน TABLE เสียก่อน
การ enable/disable row movement คำสั่งนี้สามารถทำให้ package/procedure/function ที่ผูกกับ table นี้ invalid ได้

SQL> create table temp (id number);

Table created.

SQL> alter table temp shrink space;
alter table temp shrink space
*
ERROR at line 1:
ORA-10636: ROW MOVEMENT is not enabled


SQL> alter table temp enable row movement;

Table altered.

SQL> alter table temp shrink space;

Table altered.
การใช้คำสั่ง shrink เพื่อลดขนาด segment นั้น...
ALTER TABLE...SHRINK ช่วยบีบขนาดพื้นที่ของข้อมูล และลด HWM, ถ้า SHRINK SPACE COMPACT ช่วยบีบอัดข้อมูล แต่ HWM ไม่ได้เปลี่ยนแปลง, แต่... ถ้าเรา SPACE CASCADE มันจะกระทำกับ object ที่เกี่ยวข้องด้วย

การ shrink นี้ แน่นอนสามารถใช้กับ table, index (b-tree,bit-mapped) และ object บางปรเภท
เราสามารถหาข้อมูลได้จาก Oracle Document

อีกประเด็นเกี่ยวกับการ shrink ในระหว่างที่เรา shrink, ROWID อาจจะมีการเปลี่ยนแปลง เมื่อเราย้ายข้อมูลระหว่าง block ดังนั้นก็แน่นอนอีกนั่นแหละว่า เราไม่สามารถ shrink กับ materialized view ที่ใช้ rowid และเราต้อง enable row movement

อะไรที่เราต้องกังวลเมื่อทำการลดขนาด segment ด้วยวิธีนี้, การ lock ข้อมุลในระหว่างที่กระทำการ shrink นั้นจะเป็นในระดับ row หรือ ข้อมูลใน block ที่ถูกย้าย แน่นอนมันให้ lock บน DML ที่เป็น update/delete... ในขณะที่ HWM มีการปรับเปลี่ยนจะส่งผลให้เกิด lock ในระดับ exclusive จนปรับเปลี่ยนสำเร็จ

สำหรับ index(ไม่ทำให้ unusable)ไม่มีผลกระทบ

ในบางขณะเวลา เราอาจจำเป็นที่จะต้องแบ่งงานออก เป็นสองขั้นตอน โดยการ SHRINK SPACE COMPACT จากนั้น SHRINK SPACE ตามทีหลัง

SQL> alter table temp shrink space compact;

Table altered.

SQL> alter table temp shrink space;

Table altered.
การหาพื้นที่ว่างกับ TABLE บางครั้งเราคิดถึง ALTER TABLE...MOVE
แต่... ถ้าใช้ tablespace ที่เป็น ASSM ลอง ALTER TABLE...SHRINK มันอาจจะช่วยได้