PlusMagi's Blog By Pitt Phunsanit Backend,Database,Technology อธิบายกลไกการทำ File Locking ด้วย fcntl() (Advisory locking) ตามมาตรฐาน POSIX

อธิบายกลไกการทำ File Locking ด้วย fcntl() (Advisory locking) ตามมาตรฐาน POSIX

ในระบบที่ต้องมีการทำงานพร้อมกัน (Concurrency) ของหลายโปรเซสที่เข้าถึงทรัพยากรเดียวกัน การจัดการการเข้าถึงข้อมูลจึงเป็นสิ่งสำคัญอย่างยิ่ง File Locking ด้วยฟังก์ชัน fcntl() ตามมาตรฐาน POSIX คือกลไกหลักที่ใช้ในการประสานงาน (Synchronization) ระหว่างโปรเซสเหล่านั้น

หัวใจสำคัญของกลไกนี้คือการเป็นแบบ Advisory Locking ซึ่งหมายความว่าการล็อกนี้ไม่ใช่การป้องกันทางกายภาพ (Physical Prevention) แต่เป็นการตกลงร่วมกัน (Cooperative) ระหว่างโปรเซสทั้งหมดที่เกี่ยวข้อง หากโปรเซสใดไม่สนใจการล็อกนี้ ก็สามารถเขียนทับข้อมูลได้ตามปกติ


1. Advisory Locking vs Mandatory Locking

การทำความเข้าใจความแตกต่างระหว่างสองประเภทนี้เป็นสิ่งจำเป็น:

  • Advisory Locking (แบบสมัครใจ): โปรเซสที่ต้องการเข้าถึงไฟล์ต้อง ‘ตกลง’ ร่วมกันก่อนที่จะเรียกใช้คำสั่งล็อกผ่าน fcntl() ก่อนดำเนินการอ่านหรือเขียน หากไม่มีโปรเซสใดเรียกใช้ฟังก์ชันล็อกนี้ การเข้าถึงข้อมูลก็จะไม่มีการควบคุมใดๆ จากระบบปฏิบัติการ
  • Mandatory Locking (แบบบังคับ): เป็นการล็อกที่ระดับเคอร์เนลที่เข้มงวดมาก โดยเคอร์เนลจะขัดขวางการดำเนินการ read() หรือ write() ของโปรเซสอื่นโดยอัตโนมัติทันทีที่ไฟล์ถูกล็อก (อย่างไรก็ตาม การใช้แบบ Mandatory มักซับซ้อนและเสี่ยงต่อ Deadlock ในระดับระบบสูง)

2. ชนิดของการล็อก (Lock Types) และการใช้งานใน PostgreSQL

มาตรฐาน POSIX กำหนดชนิดของล็อกผ่านโครงสร้าง struct flock ซึ่งมี 3 ชนิดหลักที่นักพัฒนาต้องทราบ:

  • Shared Lock (S_LOCK): อนุญาตให้โปรเซสหลายตัวสามารถอ่านไฟล์ได้พร้อมกัน แต่ไม่สามารถเขียนได้
  • Exclusive Lock (X_LOCK): เป็นการล็อกที่เข้มงวดที่สุด โปรเซสใดที่ได้ X_LOCK จะป้องกันไม่ให้โปรเซสอื่นทั้งอ่านและเขียนได้
  • Write Lock (W_LOCK): มักใช้แทน X_LOCK เพื่อระบุเจตนาในการแก้ไขข้อมูล

การประยุกต์ใช้ในบริบทของ PostgreSQL: แม้ว่า PostgreSQL จะเป็นระบบจัดการฐานข้อมูลที่จัดการ Concurrency ภายในด้วยกลไกของตัวเอง (เช่น MVCC และการใช้ SELECT FOR UPDATE) แต่การทำความเข้าใจ fcntl() ช่วยให้เราเข้าใจถึงระดับการล็อกที่ต่ำกว่า (OS Level) ซึ่งเป็นพื้นฐานสำคัญในการออกแบบระบบที่ต้องมีการซิงค์ข้อมูลระหว่างไฟล์ภายนอกกับฐานข้อมูล

SQL

-- ตัวอย่างแนวคิดการล็อกใน Transaction ของ PostgreSQL (ใช้ SELECT FOR UPDATE แทน fcntl()) -- นี่คือการล็อกระดับแถว (Row-level locking) ที่ PostgreSQL จัดการให้ -- โปรเซส A เริ่มต้น Transaction BEGIN; -- โปรเซส A ต้องการล็อกแถวนี้เพื่อป้องกันการแก้ไขจากโปรเซส B SELECT * FROM inventory WHERE item_id = 123 FOR UPDATE; -- โปรเซส A จะถือครอง Exclusive Lock จนกว่าจะ COMMIT; -- โปรเซส B จะต้องรอที่คำสั่ง SELECT นี้จนกว่า A จะเสร็จสิ้น; -- โปรเซส A ทำการอัปเดตข้อมูล UPDATE inventory SET stock = 5 WHERE item_id = 123; COMMIT;

บทสรุป: การจัดการ Concurrency

การทำ File Locking ด้วย fcntl() เป็นเครื่องมือพื้นฐานที่สำคัญในการควบคุมการเข้าถึงไฟล์ในระดับระบบปฏิบัติการ โดยเน้นย้ำถึงหลักการ Advisory Locking ที่โปรเซสต้องตกลงร่วมกัน การทำความเข้าใจกลไกนี้ช่วยให้นักพัฒนาสามารถออกแบบระบบที่ทนทานต่อการทำงานพร้อมกัน (High Concurrency) และสามารถเลือกใช้กลไกการล็อกที่เหมาะสม ไม่ว่าจะเป็นการล็อกระดับไฟล์ (File Lock) หรือการใช้กลไกการล็อกระดับแถว (Row Lock) ที่มีประสิทธิภาพสูงใน PostgreSQL