Posted by: siamnobita | 05/24/2010

Guess Work

หัวข้อในวันนี้มีที่มาจากกระทู้หนึ่งใน narisa.com 

คำถามในกระทู้เริ่มต้นมาจากผลลัพธ์แปลก ๆ จาก query ธรรมดา ๆ ประโยคหนึ่ง ผู้ตั้งคำถามก็แสดงทั้ง query และผลลัพธ์ให้ดูในการตั้งคำถามครั้งแรก อย่างไรก็ดีไม่มีสิ่งใดที่พอจะบอกได้เลยว่าข้อผิดพลาดนั้นจะเกิดจากที่ใด นอกจากคำบอกเล่าที่ว่า “table นี้มี index และอื่นๆ อีกมากมาย”

ผมสนใจในคำถามนี้มากทีเดียว ไม่ใช่แค่อยากช่วยคนตั้งคำถามเท่านั้น ที่จริงแล้วอยากช่วยสนองตัณหาตัวเองมากกว่า จึงโพสต์คำถามเพิ่มเติมเข้าไป แต่เนื่องจากไม่มีไอเดียอะไรในหัวเลยว่าข้อผิดพลาดนั้นมาจากไหน (รู้แต่ว่ามันต้องมาจากกลไกทำงานเบื้องหลังของ query นั้น เพราะ query มันไม่มีอะไรผิดซักนิดเดียว) จึงตั้งคำถามแบบครอบจักรวาล คนตอบกลับก็ตอบกลับแบบครอบจักรวาลเช่นเดียวกัน โดยส่ง script กลับมาให้ชุดใหญ่ น่าเสียดายที่ไม่มี execution plan ที่ขอไปกลับมาให้ด้วย

ผลลัพธ์ยังไม่เปลี่ยนแปลงคือไม่รู้ว่า ข้อผิดพลาดนั้นเกิดจากที่ใด ปฏิบัติการเดาเริ่มขึ้น ตั้งข้อสงสัยไปที่ implicit conversion เนื่องจากเห็นการใช้ data type ที่ไม่ตรงกันระหว่างคอลัมน์กับค่าที่นำมาเปรียบเทียบ รวมถึงตั้งข้อสงสัยในตัวผู้ตั้งคำถามด้วยว่าเกิดความสับสนเรื่อง schema หรือไม่ (ทั้ง ๆ ที่ไม่น่าเกี่ยวกับความเพี้ยนที่เกิดขึ้นเลย)

ผ่านไปห้าวัน ผู้ตั้งคำถามกลับมาพร้อมบอกว่าแก้ปัญหาได้แล้ว ด้วยการ drop index แล้วสร้างใหม่ และสรุปว่า “โดยสาเหตุเกิดมาจาก Index บางตัวทำงานผิดพลาด (โดยไม่ทราบสาเหตุ แต่เป็นไปได้ว่าเกิดจากการที่ไฟดับ ทำให้ server ไม่ได้ shutdown ตามขั้นตอน)”

ปัญหาของผู้ตั้งคำถามได้รับการแก้ไขเรียบร้อยแล้ว แต่ปัญหาของผมยังคาใจอยู่ จริงหรือที่ index ทำงานผิดพลาดเพราะไฟดับ ฟังก์ชั่น recovery ของ oracle มีช่องโหว่ถึงขนาดนี้เชียวหรือ ด้วยความรักใน oracle ผมอยากยืนยันว่าเป็นไปไม่ได้ แต่ด้วยความซื่อสัตย์ต่ออาชีพ ผมยังยืนยันแบบนั้นไม่ได้ เพราะไม่สามารถพิสูจน์สมมติฐานอะไรได้เลย ปัญหามันจบไปแล้วด้วยการ drop index แล้วสร้างใหม่ และผมก็ไม่สามารถเรียกร้องให้เขานำปัญหากลับมาเพื่อให้ผมหาสาเหตุต่อได้ด้วย 😦

ตามหลักมุทิตา เมื่อเขาแก้ปัญหาได้ผมก็ขอแสดงความยินดีด้วย อย่างไรก็ดี เนื่องจากสาเหตุที่วิเคราะห์มายังมีข้อน่าสงสัย ปัญหาดังกล่าวอาจเกิดขึ้นได้อีก เมื่อไฟดับ? (แซวเล่นเฉย ๆ) หนทางในการแก้ปัญหาอย่างถาวรยังต้องหาสาเหตุที่แท้จริงต่อไป ผมจึงขอบันทึกสิ่งที่ผมสงสัยเอาไว้ ณ ที่นี้

  1. execution plan ก่อนและหลังการแก้ไข มีการเปลี่ยนแปลงอย่างไร การลบและสร้าง index นอกจากตัว index ที่ใหม่แล้ว oracle จะยกเลิก plan เดิม และคำนวณ plan ออกมาใหม่ด้วย
  2. มีอะไรที่ทำงานอยู่เบื้องหลัง query นี้บ้าง ตัวอย่างเช่น implicit conversion ที่ผมสงสัยในครั้งแรก (อย่าเพิ่งเห็นว่าธรรมดาเกินไป ถ้ามันเกี่ยวกับ character set ด้วยเล่า ทีมทดสอบของ oracle ไม่ได้ตรวจสอบครบทุกกรณีแน่ ๆ อาจมี bug อยู่ที่ใดที่หนึ่ง)
  3. query ที่เรามองเห็นมันอาจไม่ใช่ query ที่รันจริง ๆ oracle มี feature อื่น ๆ ที่สามารถ rewrite query ได้อยู่มากมาย อาจต้องรัน sql trace หรือ set event trace อื่น ๆ เพื่อค้นให้พบว่าผลลัพธ์ที่ได้มานั้นออกมาจาก query อะไรกันแน่
  4. ผมยังไม่ตัดข้อสงสัยของเจ้าของกระทู้ที่ว่า โครงสร้างของ index ผิดพลาดเป็นสาเหตุของปัญหา แม้ว่าผมยังไม่สามารถเชื่อมโยงกับทฤษฎีการทำงานของ database ได้ ดังนั้นการ dump โครงสร้างของ index ใน block ที่เกี่ยวข้อง ก็อาจช่วยให้เห็นสาเหตุของปัญหาได้เช่นเดียวกัน

สุดท้ายนี้ ทุกสิ่งที่ได้สรุปเอาไว้ทั้งจากผู้ตั้งคำถามเอง และจากผมก็ล้วนแต่เป็นการเดาทั้งสิ้น ศอฉ. (ศูนย์สรุปข้อพิพาทโดยอัตโนมัติเพื่อยุติศึกแบบเฉียบพลันแต่ไม่เฉียบแหลม) ได้ข้อสรุปแล้วว่าเป็นฝีมือของผู้ก่อการร้ายนามว่า index และจะไม่มีการสืบสวนใด ๆ ต่อไป หากผู้อ่านท่านใด พบเหตุการณ์ต้องสงสัยว่าจะมีความเกี่ยวพันกับกรณีดังกล่าว ขอให้ยื่นร้องเรียนมาได้ทางช่องทางการสื่อสารของ blog นี้และเราจะได้นำคดีนี้กลับมาพิจารณาต่อไป

ขอธรรมะจงอยู่ในใจคนไทยทุกคน


Responses

  1. เคยเจอ ปัญหานี่ เช่นกัน สาเหตุ เพราะ INDEX นั่นแหละครับ

    เพราะ ตอนใช้งาน มี user insert ข้อมูล เข้ามาเยอะ แล้ว
    เคย Restart service OracleService(DBNAME) แล้ว
    พอ web abb ทำงานต่อ ไป
    insert ข้อมูล เข้าไป ในตาราง นั้นๆ
    สันนิฐานว่า ตอน Restart service OracleService(DBNAME) แล้ว ค่า Index มันดันย้อนกลับไป ช่วง ณ เวลา หนึ่ง

    แล้ว พอมีการ Insert ต่อไป ทำให้ index ที่ทำไปแล้ว และ insert ใหม่ มีึค่าตรงกัน

    เหตุการณ์ ที่เกิดคือ

    Select * from (TABLENAME) WHERE TABLENAME.COLUMBNAME = ‘XXXXXX’

    ดันมี ค่าอื่น ที่ไม่ใช่ ค่า ที่เรา ใช้เงื่อนไข WHERE มา พระเจ้า !!!

  2. ขอบคุณสำหรับรายละเอียดเพิ่มเติมครับ แต่ผมก็ยังโยงไม่ออกอยู่ดีว่ามันเกิดขึ้นได้อย่างไร และจะป้องกันปัญหาได้อย่างไร ถ้าใครมีประสบการณ์แบบเดียวกันนี้ รบกวนร่วมแชร์ด้วยก็จะดีมากครับ


ใส่ความเห็น

หมวดหมู่