Category: Database

  • การใช้ grant และ grant with grant option ใน Oracle

    การใช้คำสั่ง grant

    โดยทั่วไปเมื่อต้องการให้สิทธิ์สำหรับดำเนินการกับ object ใด ๆ ของ user หนึ่งให้กับอีก user หนึ่ง จะใช้คำสั่งคือ grant ตัวอย่าง เช่น

    • user1 เป็นเจ้าของตารางชื่อ table01
    • ในฐานข้อมูลมี user ชื่อ user2 อยู่ในฐานข้อมูลเดียวกับ user1
    • ต้องการให้ user2 สามารถใช้คำสั่ง select ข้อมูลจากตาราง table01 ของ user1
    • บน user1 ดำเนินการโดยใช้คำสั่งในการให้สิทธิ์คือ

    grant select on user1.table01 to user2;

    • หลังจากให้สิทธิ์แล้ว บน user2 สามารถใช้คำสั่งในการ select ข้อมูลจากตาราง table01 ของ user1 ได้ ตังตัวอย่างดังนี้

    select * from user1.table01; //ต้องระบุ user คั่นด้วยจุด และตามด้วยชื่อตาราง

    • การให้สิทธิ์ นอกจาก select แล้ว ยังมีสิทธิ์อื่น ๆ อีก เช่น insert, update, delete, execute ฯลฯ
    • ตัวอย่างการให้สิทธิ์มากกว่าหนึ่งสิทธิ์

    grant select, insert, update, delete on user1.table01 to user2;

    การใช้คำสั่ง grant with grant option

    รูปแบบการใช้คำสั่งคือ หลังคำสั่ง grant ปกติ ตามด้วย with grant option

    เช่น grant select on user1.table01 to user2 with grant option;

    ผลจากการใช้คำสั่ง with grant option จะมีผลให้ user ที่ได้รับสิทธิ์ สามารถให้สิทธิ์ที่ได้รับมา grant ต่อไปให้กับ user อื่นต่อได้นั่นเอง

    • ต่อเนื่องจากตัวอย่างแรก มี user3 ในฐานข้อมูลเดียวกันกับ user1 และ user2
    • เมื่อ user1 ใช้คำสั่ง

    grant select on user1.table01 to user2 with grant option;

    • มีผลทำให้ user2 สามารถ grant สิทธิ์ในการ select ให้กับ user อื่นต่อได้ เช่น

    grant select on user1.table01 to user3;

    user ที่ได้รับสิทธิ์ grant with option สามารถ ใช้ grant with option ต่อให้กับ user อื่นได้หรือไม่ ???

    • user ที่ได้รับการ grant ด้วยคำสั่ง with grant option สามารถ grant ให้ user อื่นด้วยคำสั่ง with grant option ด้วยเช่นกัน
    • ตัวอย่าง เช่น มี user4 ในฐานข้อมูลเดียวกับ user1, user2, user3
    • ต่อเนื่องจากตัวอย่างก่อนหน้านี้ user3 สามารถใช้คำสั่ง with grant option ต่อให้กับ user4 ได้ หาก user2 ได้ grant ให้ user3 ด้วยคำสั่ง with grant option

    ข้อควรระวัง

    • จะเห็นว่าในการใช้คำสั่ง grant with grant option นั้น จะทำให้ user ที่ได้รับสิทธิ์นี้ สามารถ grant สิทธิ์ต่อ ๆ กันไปให้กับ user อื่น ๆ เป็นทอด ๆ ด้วยคำสั่ง with grant option เช่นกัน
    • เมื่อ user อื่นที่ไม่ใช่เจ้าของ object ที่ถูก grant ได้รับสิทธิ์ในการ grant with option จะเห็นว่าจะทำให้การควบคุมการให้สิทธิ์ทำได้ยาก หรืออาจจะเกิดความไม่ปลอดภัยเกิดขึ้น ดังนั้น ถ้าไม่จำเป็นจึงไม่ควรให้สิทธิ์แบบ with grant option นั่นเอง

    การยกเลิกการให้สิทธิ์

    เมื่อต้องการยกเลิกการให้สิทธิ์ สามารถทำได้โดยใช้คำสั่ง revoke ตัวอย่างเช่น

    revoke select, insert, update, delete on user1.table01 from user2;

    จะเป็นการยกเลิกการให้สิทธิ์ในการ select, insert, update, delete บนตาราง table01 ของ user1 ที่เคยให้กับ user2

    ตรวจสอบได้อย่างไร ว่าเคย grant อะไรไปบ้าง

    มี view ของระบบที่ช่วยให้สามารถตรวจสอบได้ว่า object ใด ถูก grant อะไรไปบ้าง ซึ่ง view นี้เป็นของ user sys

    • view ที่เก็บข้อมูลการ grant ของ object ต่าง ๆ ชื่อ dba_tab_privs
    • มีฟีลด์ที่น่าสนใจคือ
      • grantee คือ user ที่ได้รับสิทธิ์
      • owner คือ user ที่เป็นเจ้าของ object
      • table_name คือ ชื่อ object (ชื่อของ table, view ฯลฯ)
      • grantor คือ user ที่เป็นผู้ให้สิทธิ์ (อาจจะไม่ใช่เจ้าของ object ก็ได้)
      • privilege คือ สิทธิ์ที่ได้รับ
      • grantable คือ user ที่เป็น grantee สามารถ grant สิทธิ์ต่อได้หรือไม่

  • Query ที่ใช้งานบ่อยๆสำหรับทำ ETL , Data Warehouse และ Data Science ตอนที่ 1

    สายงานดึงข้อมูลเพื่อใช้สำหรับวิเคราะห์ข้อมูล แปลงข้อมูล จัดรูปแบบข้อมูลต่างๆไม่ว่าวัตถุประสงค์ที่จะทำ ETL, Data warehouse , Data Science, Data Lake สิ่งที่จะเกิดขึ้นบ่อยๆคือ

    • การจัดกลุ่มข้อมูล ROW_NUMBER(), RANK(), DENSE_RANK()
    • การแปลงข้อมูล CAST,CASE
    • การสร้าง View, Sub Table, temp table, Material View ,select ซ้อน select หลายชั้น (with)

    การทำงานด้านนี้จะแตกต่างจากการดึงข้อมูลในการทำงานแบบ CRUD (Create, Read, Update, Delete) เป็นงาน Transaction เน้นการทำงานที่เร็วอย่างมีประสิทธิภาพ ส่วนการวิเคราะห์ข้อมูลลืมเรื่อง Performance ไปได้เลยส่วนใหญ่คำสั่งที่ทาง Transaction Performance ต้องการให้เราหลีกเลี่ยงเราก็จะได้นำมาใช้งานอยากสนุกสนาน
    เนื่องจากตอนนี้ผมดึงข้อมูลจาก Oracle Database เป็นหลักก็เลยขอเขียนตัวอย่างของ Oracle ก่อนนะครับ ต่อไปค่อยเพิ่มเติม Database อื่นๆต่อไป

    การจัดกลุ่มข้อมูล

    พื้นฐานสุดๆที่รู้ๆกันคือการทำด้วยคำสั่ง Group By เช่น
    ถ้าเราต้องการค่าเดียวจากตารางเลย select sum(a) from table_a แบบนี้ก็จะเป็นการ Group ข้อมูลทั้งตาราง
    ถ้าต้องการมีตัวแยกข้อมูลก็จะเป็น select column_a,count(*) from table_a group by column_a แบบนี้ก็จะมีตัวช่วยแบ่งกลุ่มข้อมูลออกมาแล้ว
    แต่การทำงานจริงไม่ได้ง่ายดายขนาดนั้น เช่น โจทย์ต้องการเอาค่าที่มากสุด น้อยสุดหรือล่าสุดของข้อมูลในตารางโดยต้องแบ่งข้อมูลออกเป็นส่วนๆตามที่ต้องการก่อน อันนี้ก็จะพอไหว แต่ถ้าบอกว่าต้องการเอาข้อมูลลำดับที่ 1 และลำดับที่ 2 ของข้อมูลมาเปรียบเทียบกันซึ่งไม่สนใจลำดับอื่นๆแบบนี้การแบ่งกลุ่มก็ต้องมาการจัดลำดับ และสามารถดึงลำดับที่ต้องการออกมาได้ อันนี้ยากแล้วเราก็ต้องมาดูว่าฐานข้อมูลแต่ละแบบมีตัวช่วยอะไรให้เราใช้บ้างในส่วนของ oracle จะมีฟังก์ชันกลุ่มนึงที่เป็นการเรียงลำดับข้อมูลนั่นก็คือ ROW_NUMBER(),  RANK(), DENSE_RANK() 

    ROW_NUMBER() ใช้สำหรับแป๊ะเลขที่ ของชุดข้อมูลที่สนใจ ถ้าไม่ Partition ข้อมูลก็จะเป็นการ แป๊ะเลขที่ของข้อมูลทั้งหมด ซึ่งใน Oracle จะมี อีกตัวไว้ใช้งานอยู่แล้วคือ ROWNUM ซึ่งเป็น pseudocolumn ไม่ต้องใช้ ROW_NUMBER() แต่ถ้าต้องการแบ่งข้อมูลออกเป็นส่วนๆด้วย ก็ต้องใช้ ROW_NUMBER บวกกับ PARTITION BY ลองดูตัวอย่างการทำงานจริงๆครับกว่าจะได้คำตอบมาต้องทำกี่ขั้นดังนี้

    รูป Row_Number()

    จากรูปอธิบายได้ดังนี้

    ชั้นในสุดต้องการหาผลนับจำนวนข้อมูลที่สนใจ
    ชั้นที่ 2 เอาข้อมูลที่ได้มาแบ่ง Partition By ด้วย data_year และเอามาเรียงลำดับ Order By ด้วย Totals แบบเรียงจากมากไปน้อย DESC โดยจะใส่เลขกำกับไว้กับข้อมูลที่ data_year เดียวกันที่มีค่า totals มากที่สุดจะเป็นเลข 1 ไปเรื่อยๆ และเริ่ม 1 อีกครั้งเมื่อ data_year เปลี่ยนไป
    ชั้นนอกสุด คือ select * from (…) where row_no < 4 คือเอามาเฉพาะลำดับที่ 1-3 เท่านั้น
    สรุปคือต้องการเอาข้อมูลรายชื่อคณะที่มีค่า totals มากที่สุด 3 ลำดับแรกของแต่ละ data_year ออกมาแสดง

    RANK()

    ลักษณะการทำงานก็จะเหมือนตัวอย่าง ROW_NUMBER() จะเขียนอธิบายเฉพาะที่แตกต่างกันเท่านั้นดังนี้
    เป็นการแป๊ะตัวเลขลำดับให้กับชุดข้อมูลเดียวกัน แต่ค่าข้อมูลที่สนใจได้ลำดับเดียวกัน จะข้ามตัวเลขลำดับถันไปเท่ากับจำนวนลำดับที่เท่ากัน ดังรูปผลของ Query ด้านล่าง จากลำดับที่ 2 ไป 3 rows แล้วจะไปขึ้นลำดับที่ 5 เลย

    DENSE_RANK()

    จะเหมือนกัน RANK() แต่จะไม่มีการเว้นเลขลำดับ จะมีเลขที่ต่อเนื่องไปเลย ดังรูปผลของ Query ด้านล่าง จากลำดับที่ 2 ไป 3 rows แล้วจะต่อลำดับที่ 3 ต่อไป

    รูปตัวอย่าง Query
    รูปผลของ Query

    การแปลงข้อมูล

    CAST

    ใช้เพื่อแปลงชนิดของข้อมูลให้เป็นไปตามที่ต้องการ เช่น แปลงวันที่เป็นข้อความ กำหนดชนิดของข้อมูล Column ที่ยังไม่มีข้อมูลให้เป็นไปตามที่ต้องการ ดังตัวอย่าง

    รูปการแปลงวันที่ปัจจุบันเป็นข้อความ
    รูปผลการแปลงวันที่ปัจจุบันเป็นข้อความ
    รูปแสดงการสร้างตารางใหม่จากข้อมูลที่มีอยู่และต้องการเพิ่ม column ใหม่เข้าไปเพิ่มเติมแบบต้องการระบุ data type

    CASE

    ใช้เพื่อจัดการข้อมูลในหลายๆรูปแบบเป็นการกำหนดเงื่อนไขขึ้นมาเพื่อแปลงข้อมูล ดังตัวอย่าง ต้องการ Update Column ให้มีค่าแตกต่างกันให้เป็นไปตามเงื่อนไขที่กำหนด

    update student_regist
    set WITHDRAWAL_TYPE =  case
                                when lower(WITHDRAWAL_TYPE) = 'w' then  'ถอนติด W' 
                                when lower(WITHDRAWAL_TYPE) = 'c' then  'ถอนเพราะวิชาปิด'
                                when lower(WITHDRAWAL_TYPE) = 'r' then  'ถอน'
                                when lower(WITHDRAWAL_TYPE) = 'n' then  'ถอน'
                                when lower(WITHDRAWAL_TYPE) is null then  'ลงทะเบียนปกติ'
                                else 'xxx'
                                end;

    การสร้าง VIEW, Temporary Table, Materialized view

    การแยกข้อมูลออกเป็นกลุ่มๆอีกวิธีที่ใช้งานเยอะคือการสร้าง View, Temporary Table, Materialized view

    View

    มีการเปลี่ยนแปลงตาม Table ต้นทาง View ไม่น่าจะต้องพูดเยอะเพราะน่าจะใช้งานกันเป็นประจำอยู่แล้ว

    Materialized view

    เป็นตารางที่มีข้อมูลที่ได้มาจากผลของการ Run Query ที่เราต้องการและมีการ Refresh ข้อมูลตามเวลาที่กำหนดไว้ ที่แตกต่างจาก View คือต้องการที่จัดเก็บข้อมูลส่วนตัวนะครับ ตัวอย่างการสร้าง Materialized View

    DROP MATERIALIZED VIEW REGIST_ALL;
    
    CREATE MATERIALIZED VIEW REGIST59
    BUILD IMMEDIATE
    REFRESH COMPLETE
    START WITH sysdate
    NEXT sysdate+1
    WITH PRIMARY KEY
    AS
    SELECT *
    FROM REGIST where year >'2558';
    
    COMMENT ON MATERIALIZED VIEW REGIST59 IS 'snapshot table for snapshot REGIST';

    Temporary Table

    Temporary Table ใน Oracle ใช้แก้ไขปัญหาที่ซับซ้อนโดยการใช้  Stored Procedure หาข้อมูลแล้วนำไปเก็บไว้ใน Temporary table เพื่อประมวลผลในขั้นถัดๆไป

    CREATE GLOBAL TEMPORARY TABLE temp_table (
    
      student_id NUMBER(1),
    
      student_name            VARCHAR2(150),
    
      country_name    VARCHAR2(150)
    
    )
    ON COMMIT DELETE ROWS;

    ตัวอย่างการสร้าง temporary Table ไว้ใช้งาน ON COMMIT DELETE ROWS; เป็นการบอกว่า เมื่อใช้งานเสร็จให้ลบข้อมูล อย่างเช่นสั่ง insert ข้อมูลใน stored procedure เมื่อ stored procedure ทำงานเสร็จข้อมูลที่ insert ไว้ใน temporary table จะถูกลบทิ้งทั้งหมด เป็นต้น ยังมี option อีกมากมายสำหรับ temporary table ต้องศึกษาจาก Oracle Document

    Subquery

    subquery เป็นตัวช่วยทำงานในการแยกข้อมูลที่ต้องการออกมาเป็นส่วนๆแล้วนำไปประมวลผลต่อ ในกลุ่มนี้ with … as ถือว่ามีการใช้งานบ่อยครั้ง คำสั่ง With … as ข้อมูลที่ได้มาเปรียบได้กับ local temporary 1 table นำไป query ต่อได้

    WITH dept_count AS (
      SELECT deptno, COUNT(*) AS dept_count
      FROM   emp
      GROUP BY deptno)
    SELECT e.ename AS employee_name,
           dc.dept_count AS emp_dept_count
    FROM   emp e
           JOIN dept_count dc ON e.deptno = dc.deptno;

    จากตัวอย่างนี้เป็นการนับจำนวนหน่วยงานตาม deptno แล้วเอามา Join กับ table emp ที่มีค่า deptno ตรงกัน

    ตอนที่ 1 นี้ขอจบแต่เพียงเท่านี้ ตอนต่อๆไปจะเรียบเรียงข้อมูลตามที่ใช้ทำงานจริงๆในการทำงานด้าน ETL, Data Science และ Data Lake ต่อไปนะครับ ขอบคุณที่เข้ามาอ่านกันนะครับ

  • กำหนด Lexer สำหรับ Full Text Search บน ฐานข้อมูล Oracle เพื่อค้นหาภาษาไทยให้ถูกต้อง

    เนื่องจากระบบสืบค้นที่ดูแลอยู่เจอปัญหาค้นหาเลขไทย “๑ ๒ ๓ …” ไม่เจอ หลังจากตรวจสอบจนแน่ใจแล้วว่าก่อนจะส่งคำสั่ง Query ไปยังฐานข้อมูลไม่ได้เผลอตัดเลขไทยออกที่ขั้นตอนไหน จึงทำการตรวจสอบคำสั่งที่ใช้ในการค้นหา พบว่าใช้ฟังก์ชัน

    SELECT * FROM THAI_LIBRARY WHERE CONTAINS(BOOK_NAME, '๑๐๐ ปีชาติไทย', 1) > 0;

    จากคำสั่ง (ที่สมมุติขึ้น) ด้านบนจะเห็นได้ว่าใช้ CONTAINS ซึ่งเป็นฟังก์ชันที่อยู่ในกลุ่ม Oracle Text ซึ่งฟังก์ชันนี้จะค้นหาคำใกล้เคียงจาก Index แล้วคืนค่า Score มาให้เราเพื่อใช้เป็นเงื่อนไขพิจารณาว่าจะใช้ข้อมูลรายการนั้นหรือไม่

    ที่มาภาพ

    ภาพด้านบนแสดงขั้นตอนการสร้าง Oracle Text Index เนื่องจากระบบจัดเก็บข้อมูลเป็น Text อยู่แล้วจึงไม่มีการกำหนด Fillter, Sectioner ทำให้จุดที่ต้องตรวจสอบว่า เลขไทยเราหายไปจาก Index ได้ยังไงเหลืออยู่คือ Lexer ที่จะเป็นตัวกำหนด Wordlist, Stoplist ในการทำ Index ต่อไป ไปดูว่ามี Lexer อะไรบ้าง

    จากตารางด้านบน เนื่องจากฐานข้อมูลของระบบที่ดูแลอยู่ประกอบไปด้วย ภาษาไทย ภาษาอังกฤษ เป็นหลัก และอาจจะมีภาษาอื่นๆปนอยู่ด้วย Lexer ที่น่าจะใช้ได้คือ AUTO_LEXER, MULTI_LEXER, WORLD_LEXER หลังจากได้ทดสอบกำหนดค่า Lexer ให้กับฐานข้อมูล และทดสอบค้นหาด้วย เลขไทย พบว่าจะต้องใช้ WORLD_LEXER จึงจะสามารถรองรับกรณีนี้ได้ โดยใช้คำสั่งดังนี้

    EXEC CTX_DDL.CREATE_PREFERENCE('WorldLex', 'world_lexer');

    DROP INDEX USER01.IDXFT_THAI_LIBRARY_BOOKNAME;
    CREATE INDEX USER01.IDXFT_THAI_LIBRARY_BOOKNAME ON USER01.THAI_LIBRARY(BOOK_NAME)
    INDEXTYPE IS CTXSYS.CONTEXT
    PARAMETERS('LEXER WorldLex STOPLIST CTXSYS.EMPTY_STOPLIST SYNC(ON COMMIT)')
    NOPARALLEL;

    USER01 คือ User ของฐานข้อมูล Oracle

    THAI_LIBRARY คือ ชื่อตาราง

    BOOK_NAME คือ ชื่อคอลัมภ์ ที่ต้องการทำ Index

    IDXFT_THAI_LIBRARY_BOOKNAME ชื่อ ตาราง index

    ผลพลอยได้ จากการปรับในครั้งนี้พบว่าเดิมต้องทำการตัดคำให้เรียบร้อย (เนื่องจากค่า Default คือ Basic Lexer ที่แบ่งคำด้วยช่องว่างเท่านั้น) เพื่อค้นหา แต่เมื่อปรับ Lexer ให้ถูกต้องสามารถส่งคำค้นเป็นประโยคยาวๆ ไปค้นหาได้เลย หวังว่าบทความนี้จะเป็นประโยชน์กับท่านที่ใช้งาน Full Text Search ของ Oracle และประสบปัญหาคล้ายๆกันนี้ครับ

  • Migrate จากฐานข้อมูล MySql มายัง Oracle ด้วย Sql Developer

    เนื่องจากงานที่รับผิดชอบ จะต้องมีการโอนย้ายข้อมูลจากฐานข้อมูลอื่นๆมายัง Oracle เป็นประจำ พบว่าการย้าย MySql มายัง Oracle นั้นสามารถทำได้ง่ายมาก (อาจเพราะเจ้าของเดียวกัน) โดยมีวิธีดังนี้

    1. ดาวส์โหลดและติดตั้ง Oracle SQL Developer

    2. ทำการเชื่อมต่อไปยังฐานข้อมูล Oracle ด้วย User system

    3. สร้าง Oracle User สำหรับเก็บข้อมูลจาก MySql และกำหนดสิทธิให้เรียบร้อย

    4. ดาวส์โหลดไฟล์ Third Party JDBC Driver สำหรับ My Sql

    5. เปิดการใช้งาน Third Party JDBC Driver โดยไปที่ Tools > Preferences > Database > Third Party JDBC Drivers

    6. ทำการ Restart โปรแกรม Sql Developer เมื่อทำการ New Connection จะมีตัวเลือกเพื่อเชื่อมต่อไปยัง My Sql

    7. ทำการเชื่อมต่อไปยัง My Sql  หากต้องการเพียง Data, Schema สามารถคลิกขวาตารางที่ต้องการเลือก Copy To Oracle ได้เลย

    เพียงเท่านี้ ข้อมูล Table, Field ก็จะถูกโอนย้ายและ Map Data Type ให้อัตโนมัติสามารถ Query จาก Oracle ได้เลย

    แต่สำหรับงานที่ต้องการ Constraint, Trigger, ฯลฯ ด้วย จะมีขั้นตอนเพิ่มเติมดังนี้

    1. ไปที่  Tools > Migration > Migrate กำหนด User ที่จะใช้เป็น Migrate Repository (เก็บข้อมูลต่างๆขณะดำเนินการ Migrate)

    2. กำหนดโฟลเดอร์จัดเก็บ Script, Log file

    3. เลือก Connection My Sql ที่ต้องการ Migrate

    4. เลือก My Sql User ที่ต้องการ Migrate

    5. การ Map Data Type สามารถใช้ค่า Default ได้

    6. เลือก Sql Object ที่ต้องการ

    7. เลือก Connection ของ DB User ที่ใช้เก็บโครงสร้าง และคำสั่งต่างๆ ที่ระบบใช้ในการ Migrate

    8. กำหนด User เป้าหมายที่จะนำข้อมูลเข้า จากนั้นเลือก Finish

    เพียงเท่านี้ก็เรียบร้อยครับ ข้อควรระวังคือการเลือก Repository User ควรสร้างขึ้นมาใหม่ เนื่องจากจะมีการสร้าง Table ขึ้นมาระหว่างการ Migrate และการกำหนดสิทธิให้กับ User ต่างๆให้ครบถ้วน แบบที่สองดูเหมือนหลายขั้นตอน แต่ก็เป็นแบบ Wizard ที่ใช้งานได้ไม่ยาก หวังว่าบทความนี้จะเป็นประโยชน์ครับ

  • Grid Infrastructure 18c ตอน 5 (ตอนจบภาคติดตั้ง)

    • ตอนนี้จะมาติดตั้ง oracle database 18c
    • เข้าระบบด้วยผู้ใช้ oracle เปิด terminal พิมพ์คำสั่ง (จากครั้งที่แล้วยังเหลือ disk อีก 2 ลูก)
    grid_env
    sqlplus / as sysasm
    • ต่อด้วยคำสั่ง SQL ต่อไปนี้
    CREATE DISKGROUP data EXTERNAL REDUNDANCY DISK '/dev/oracleasm/disks/DISK5'
           ATTRIBUTE 'compatible.asm'='18.0','compatible.rdbms'='18.0';
    CREATE DISKGROUP reco EXTERNAL REDUNDANCY DISK '/dev/oracleasm/disks/DISK6'
           ATTRIBUTE 'compatible.asm'='18.0','compatible.rdbms'='18.0';
    exit;
    • ได้ดังรูป
    • เริ่มติดตั้ง database
    db_env
    cd $ORACLE_HOME
    ./runInstaller
    • ได้ดังรูป
    Select Configuration Option
    • Set Up Software Only
    • กด Next ได้ดังรูป
    • เลือก Oracle Real Application Clusters database installation ได้ดังรูป
    • กด Next ได้ดังรูป
    • เลือก Standard Edition 2 กด Next
    • กด Next
    • กด Next
    • รอแป๊บ
    • กด Install
    • รอจนมีหน้าต่างใหม่ว่า
    • เปิด Terminal แล้วพิมพ์คำสั่งต่อไปนี้ ที่ rac1 และ rac2
    sudo /u01/app/oracle/product/18.0.0.0/db_1/root.sh
    • กลับไปที่หน้าต่าง Execute Configuration Scripts กด OK
    • กด Close
    • ต่อไปสร้าง database ด้วยคำสั่ง
    dbca
    • จะได้
    • เลือก Create a database กด Next
    • กด Next
    • เลือกดังรูปกด Next
    • กด Next
    • ตั้ง Global database name และ SID Prefix เอาเครื่องหมายถูกหน้า Create Container database ออก กด Next
    • คลิก Browse…
    • เลือก DATA กด OK
    • กด Next
    • คลิกเลือก Specify Fast Recovery Area Browse ไฟล์เลือก +MGMT ช่อง Fast Recovery Area size: เป็นขนาด HDD–10%
    • กด Next
    • ปรับแต่ง memory ตามความเหมาะสม คลิกช่อง Sizing ปรับจำนวนโปรเซส
    • กดช่อง Character sets
    • เลือกตามรูป กด Next
    • กด Next
    • ตั้ง Password กด Next
    • กด Next
    • รอแป๊บ
    • กด Finish
    • รอระหว่างนี้ไปพักได้
    • กด Close
    • เสร็จ

    สิ่งที่ต้องหาข้อมูลเพิ่มเติม

    • disk group ต่างๆ ไว้ทำอะไร และอาจปรับลดให้เหลือเฉพาะ disk group เดียว จะได้มีเนื้อที่มากขึ้นกว่าตอนนี้ ที่มีแค่ 1TB
    • automatic start/stop server
      • ตอนนี้ทำเสร็จไม่สามารถ restart ได้เพราะทำไม่เป็น
    • ทำแค่ how to ติดตั้งเพียงอย่างเดียวจึงได้เพียงเท่านี้
    • จบขอให้สนุก
  • Grid Infrastructure 18c ตอน 4

    • โหมดแทบ จะ next technology
    • เข้าระบบด้วยผู้ใช้ oracle เปิด terminal พิมพ์คำสั่งต่อไปนี้
    grid_env
    cd $ORACLE_HOME
    ./gridSetup.sh
    • จะได้ดังรูป
    Select Configuration Option
    • เลือก Configure Oracle Grid Infrastructure for New Cluster กด Next
    • จะได้ดังรูป
    Select Cluster Configuration
    • เลือก Configure an Oracle Standalone Cluster กด Next
    • จะได้ดังรูป
    Grid Plug and Play Information
    • เลือก Create Local SCAN
    • แก้ชื่อให้ตรงกับที่ขอจดกับ DNS (rac-scan) ดังรูป
    Grid Plug and Play Information
    • กด Next จะได้ดังรูป
    Cluster Node Information
    • ให้กด Add… เพื่อเพิ่ม rac2 ดังรูป
    Cluster Nod Information
    • กด Next จะได้ดังรูป
    Specify Network Interface Usage
    • ให้เปลี่ยนเป็นตามรูป (ซึ่งตัวอย่างนี้ใช้ iSCSI)
    Specify Network Interface Usage
    • กด Next จะได้ดังรูป
    Storage Option Information
    • เลือก Configure ASM using block devices กด Next
    • จะได้
    Grid Infrastructure Management Repository Option
    • เลือก Yes กด Next
    • ได้ดังรูป
    Create ASM Disk Group
    • เปลี่ยน Disk Discovery Path เป็น /dev/oracleasm/disks/* โดยการคลิก Change Discovery Path…
    Change Disk Discovery
    • คลิก Specify Failure Groups… กรอกและเลือกดังรูป กด OK
    Failure Groups
    • ในส่วนของ Redundancy เลือก Normal
    • ในช่อง Select Disks เลือก Disk 3 ลูก ระบุ Failure Group ต่างกัน Group ตามที่สร้างไว้
    Create ASM Disk Group
    • กด Next จะได้ดังรูป
    GIMR Data Disk Group
    • เลือก External และ disk 1 ลูก
    GIMR Data Disk Group
    • กด Next จะได้
    Specify ASM Password
    • เลือก Use same passwords for these accounts แล้ว ตั้ง password
    Specify ASM Password
    • กด Next ได้ดังรูป
    Failure Isolation Support
    • เลือก Do not use Intelligent Platform Management Interface (IPMI) กด Next ได้ดังรูป
    Specify Management Options
    • กด Next แล้วเลือกดังรูป dba, oper, asmoper
    Privileged Operating System Groups
    • จะได้ดังรูป
    Specify Installation Location
    • กด Next ได้ดังรูป
    Oracle Grid Infrastructure 18c Installer
    • เลือก Yes ได้ดังรูป
    • กด Next ได้ดังรูป
    Root script execution configuration
    • กด next ได้ดังรูป
    Perform Prerequisite Checks
    Summary
    • กด Install ได้ดังรูป
    • รอจนกระทั่ง
    Execute Configuration Scripts
    • ให้รันคำสั่งต่อไปนี้ ใน terminal เริ่มจาก rac1 แล้วต่อด้วย rac2
    sudo /u01/app/oraInventory/orainstRoot.sh
    orainstRoot.sh
    sudo /u01/app/18.0.0.0/grid/root.sh
    • กด enter 1 ครั้งแล้วรอ ให้สคริปต์ทำงานไปจนกว่าจะเสร็จ โดยสังเกตด้วยต้องไม่มีคำว่า Fail เลย
    • เมื่อครบทั้ง 2 คำสั่งที่ rac1 แล้ว ให้ทำซ้ำที่ rac2 อาจสั่งไปจาก rac1 ก็ได้
    ssh rac2
    • เมื่อสั่งคำสั่งครบทั้ง 2 เครื่องแล้วให้กลับมา rac1 แล้วกด OK ได้รูป
    Oracle Grid Infrastructure 18c Installer – Step 18 of 19
    • พักดื่มน้ำปัสสาวะได้ เนื่องจากค่อนข้างนาน
    • กลับมากด Close ได้เลย
    Finish
    • ต่อไปติดตั้ง database ตอน 5 ใกล้ละๆ
    https://sysadmin.psu.ac.th/2021/01/27/grid-infrastructure-18c-5/
  • Grid Infrastructure 18c ตอน 3

    downloaded 
    • ไฟล์ที่ download จาก https://edelivery.oracle.com จะมี 2 ไฟล์คือ
      • V978967-01.zip คือ ไฟล์ติดตั้ง database
      • V978971-01.zip คือ ไฟล์ติดตั้ง grid infrastructure
      • download ไฟล์มาเก็บไว้ที่ /home/oracle/Downloads ของ rac1 เครื่องเดียว
    • เข้าระบบด้วย ผู้ใช้ oracle เปิด terminal
    • unzip
    db_env
    cd $ORACLE_HOME
    unzip /home/oracle/Downloads/V978967-01.zip
    grid_env
    cd $ORACLE_HOME
    unzip /home/oracle/Downloads/V978971-01.zip
    • สร้าง User Equivalence (Key-Based Authentication) ระหว่าง rac1 และ rac2
    ssh-keygen -t rsa #enter ผ่านไปเรื่อยๆ จนได้ prompt $
    • จากนั้นตามด้วยคำสั่ง
    ssh-copy-id rac2
    • พิมพ์ yes แล้วใส่รหัสผ่านของ rac2
    • ทดสอบ
    ssh rac2 date
    • ต้องได้ผลลัพธ์ประมาณว่า
    ssh rac2 date
    • ทำซ้ำที่ rac2
    ssh rac1 date
    • ติดตั้ง cvuqdisk.rpm ด้วยคำสั่ง
    sudo rpm -iUvh /u01/app/18.0.0.0/grid/cv/rpm/cvuqdisk-1.0.10-1.rpm
    • ส่งไฟล์ cvuqdisk-1.0.10-1.rpm ไปให้ rac2
    scp /u01/app/18.0.0.0/grid/cv/rpm/cvuqdisk-1.0.10-1.rpm rac2:/home/oracle
    • ติดตั้ง cvuqdisk ที่ rac2 ด้วยคำสั่ง
    sudo rpm -iUvh cvuqdisk-1.0.10-1.rpm
    • สั่งคำสั่งต่อไปนี้ ที่ rac1 และ rac2
    sudo systemctl stop avahi-daemon.socket
    sudo systemctl disable avahi-daemon
    • สั่งคำสั่งต่อไปนี้ที่ rac1
    grid_env
    cd /u01/app/18.0.0.0/grid/
    ./runcluvfy.sh stage -pre crsinst -n rac1,rac2 -fixup -verbose
    • ต้องได้ผลเป็น PASSED ทั้งหมด
    • จบเตรียมเครื่อง
    https://sysadmin.psu.ac.th/2021/01/21/grid-infrastructure-%e0%b8%95%e0%b8%ad%e0%b8%99-4/
  • Grid Infrastructure 18c ตอน 2

    • ตอนสองจัดการ Shared disk
      • ล็อคอินด้วยผู้ใช้ oracle เปิด terminal พิมพ์คำสั่ง ต่อไปนี้ เพื่อเป็น root เมื่อถามรหัสผ่าน ให้ใส่รหัสผ่านของ oracle
    sudo -i
    • ตรวจสอบว่ามีแฟ้ม /etc/multipath.conf หรือไม่ หากไม่มีให้สั่งคำสั่งต่อไปนี้
    mpathconf --enable
    systemctl start multipathd
    systemctl enable multipathd
    • ตรวจสอบ shared disk ด้วยคำสั่ง
    ls -l /dev/mapper/mpath?
    shared disk
    • จะเห็นว่ามี mpatha ถึง mpathf
    • สร้าง partition บน mpatha ถึง mpathf ด้วยคำสั่ง
    fdisk  /dev/mapper/mpatha
    • สร้าง partition ใหม่ตามขั้นตอนเดิม n แล้ว enter 4 ครั้ง แล้วกด w แล้ว enter ทำจนครบ ถึง mpathf
    • เนื่องจากเป็น shared disk แบ่ง partition ที่เดียวก็จะได้ทั้งสองเครื่อง ที่ rac2 เข้าระบบด้วย oracle แล้วเป็น root ด้วยคำสั่ง
    sudo -i
    • แล้วพิมพ์คำสั่งต่อไปนี้เพื่อ update ตาราง partition
    partprobe
    • กลับมาที่ rac1 ติดตั้ง oracleasm-support และ kmod-oracleasm ด้วยคำสั่ง
    yum install -y kmod-oracleasm oracleasm-support
    • ตั้งค่า oracleasm ด้วยคำสั่ง
     oracleasm configure -i
    • แล้วกรอกตามภาพ
    oracleasm configure
    • โหลด kernel module ด้วยคำสั่ง
    oracleasm init

    ได้ผลดังภาพ

    oracleasm
    • ทำซ้ำอีกครั้งที่ rac2
    • กลับมา rac1 พิมพ์คำสั่งต่อไปนี้เพื่อสร้าง oracleasm disk โดย DISK* คือขื่อ disk
    oracleasm createdisk DISK1 /dev/mapper/mpatha1
    oracleasm createdisk DISK2 /dev/mapper/mpathb1
    oracleasm createdisk DISK3 /dev/mapper/mpathc1
    oracleasm createdisk DISK4 /dev/mapper/mpathd1
    oracleasm createdisk DISK5 /dev/mapper/mpathe1
    oracleasm createdisk DISK6 /dev/mapper/mpathf1
    • ที่ rac2 พิมพ์คำสั่ง
    oracleasm scandisks
    oracleasm scandisks
    • ที่ rac1 terminal พิมพ์ exit
      • พิมพ์ oracleasm listdisks
    • ที่ rac2 terminal พิมพ์ exit
      • พิมพ์ oracleasm listdisks
    oracleasm listdisks
    • ต้องได้ผลเหมือนกันทั้งสองเครื่อง
    • จบจัดการ shared disk
    https://sysadmin.psu.ac.th/2021/01/19/grid-infrastructure-3/
  • วิธีเรียกข้อมูล ข้าม Database บน Postgresql

    บน Postgresql สามารถเรียกข้อมูลข้าม Database ได้ แต่ต้องสั่งติดตั้ง dblink extension ก่อน ด้วยคำสั่ง

     create extension dblink; 

    จากนั้น ใช้คำสั่ง dblink() ใน FROM clause ซึ่ง Function นี้ จะต้อง return records มา ซึ่งเราจะต้องกำหนดชนิดของข้อมูลด้วย

    ดังตัวอย่างนี้

    SELECT 
       t.id, t.fullname, t.dob
    FROM 
       dblink(
       'dbname=otherdatabase options=-csearch_path=schema_name',
       '
         SELECT
           id,
           fullname,
           dob, 
         FROM sometable
       ' ) as t(
            id int,
            fullname text,
            dob date,  
       )

    เป็นการเรียกไปยัง Database ชื่อ otherdatabase, Schema ชื่อ schema_name และเรียกข้อมูลจาก Table ชื่อ sometable โดยมี field ชื่อ id, fullname, dob

    หลังคำสั่ง dblink ต้องกำหนด้วยว่า records ที่ได้กลับมา มี Datatype เป็นอะไรบ้าง

    ในตัวอย่างข้างต้น กำหนด id เป็น Integer, fullname เป็น Text และ dob (วันเกิด — Date of birth) เป็น Date

    แต่ถ้าอีก Database นั้น ให้สิทธิ์ user ที่ติดต่อเข้าไป ไม่ใช่ super user จะต้องระบุ username, password ดังตัวอย่างนี้

    dblink(
    'dbname=otherdatabase user=db_username password=db_password options=-csearch_path=schema_name', ...)

    เป็นการติดต่อ Database: otherdatabase, User: db_username, Password: db_password, Schema: schema_name

    หวังว่าจะเป็นประโยชน์ครับ