ปัญหาการขยายตัวที่สำคัญของฟีเจอร์ LISTEN/NOTIFY ของ PostgreSQL ได้จุดประกายการอพยพอย่างกว้างขวางในชุมชนนักพัฒนา หลังจากที่ Recall.ai แบ่งปันประสบการณ์เกี่ยวกับปัญหาประสิทธิภาพฐานข้อมูล บริษัทได้ค้นพบว่าฟีเจอร์ที่ดูเหมือนไม่เป็นอันตรายนี้สามารถทำให้ระบบฐานข้อมูลทั้งหมดล่มได้ภายใต้โหลดการเขียนพร้อมกันที่หนัก
ปัญหาการล็อกทั้งระบบที่ซ่อนอยู่
ฟีเจอร์ LISTEN/NOTIFY ของ PostgreSQL ซึ่งมักใช้สำหรับการแจ้งเตือนแบบเรียลไทม์และรูปแบบ pub-sub มีข้อจำกัดทางสถาปัตยกรรมที่น่าประหลาดใจ เมื่อคำสั่ง NOTIFY ทำงานภายในธุรกรรม มันจะได้รับการล็อกทั้งระบบในฐานข้อมูลทั้งหมดในระหว่างขั้นตอนการคอมมิต สิ่งนี้ทำให้การคอมมิตฐานข้อมูลทั้งหมดกลายเป็นการเข้าแถวเดียว ทำลายความสามารถในการจัดการกับผู้เขียนหลายคนพร้อมกันอย่างสิ้นเชิง
ปัญหานี้จะรุนแรงเป็นพิเศษภายใต้สถานการณ์ที่มีการใช้งานพร้อมกันสูง Recall.ai ประสบปัญหานี้โดยตรงเมื่อประมวลผลการบันทึกการประชุมหลายล้านชั่วโมงด้วยผู้เขียนพร้อมกันหลายหมื่นคน โหลดฐานข้อมูลของพวกเขาเพิ่มขึ้นอย่างมาก แต่การใช้งาน CPU และดิสก์กลับลดลง ซึ่งเป็นสัญญาณที่ชัดเจนว่าระบบติดอยู่กับการรอการล็อกมากกว่าการทำงานจริง
หมายเหตุ: การล็อกทั้งระบบหมายความว่ามีเพียงการดำเนินการเดียวเท่านั้นที่สามารถดำเนินการได้ในแต่ละครั้งทั่วทั้งฐานข้อมูล ซึ่งจะบล็อกธุรกรรมอื่นๆ ทั้งหมดจากการเสร็จสิ้น
ปัญหาการขยายขนาดของ PostgreSQL LISTEN/NOTIFY:
- ปัญหา: การล็อกฐานข้อมูลแบบ Global ในระหว่างขั้นตอน NOTIFY commit
- ผลกระทบ: ทำให้การ commit ฐานข้อมูลทั้งหมดต้องเรียงคิวกันภายใต้การเขียนข้อมูลพร้อมกัน
- อาการ: ฐานข้อมูลมีโหลดสูง การใช้งาน CPU/disk ต่ำ อัตราการประมวลผล query ลดลงอย่างมาก
- เกณฑ์การขยายขนาด: เริ่มมีปัญหาเมื่อมี writer พร้อมกันหลักหมื่นตัว
- ประเภทการล็อก: AccessExclusiveLock บน object 0 ของ class 1262 ของ database 0
![]() |
---|
เมตริกประสิทธิภาพของระบบที่เน้นผลกระทบของ global locking ต่อการดำเนินงานของฐานข้อมูล |
ปฏิกิริยาของชุมชนและทางเลือกอื่น
ชุมชนนักพัฒนาได้ตอบสนองด้วยการผสมผสานระหว่างการพูดว่า เราบอกคุณแล้ว และความกังวลที่แท้จริงเกี่ยวกับข้อจำกัดที่มีเอกสารไม่ดีนี้ นักพัฒนาที่มีประสบการณ์หลายคนชี้ให้เห็นว่า PostgreSQL เป็นเลิศในการดำเนินการข้อมูลเชิงสัมพันธ์ แต่ต่อสู้กับโหลดงาน pub-sub ที่มีการใช้งานพร้อมกันสูง
แนวทางทางเลือกหลายแนวทางได้เกิดขึ้นจากการอภิปราย นักพัฒนาบางคนแนะนำให้ใช้คิวข้อความเฉพาะเช่น NATS หรือ Redis สำหรับการดำเนินการ pub-sub ในขณะที่คนอื่นๆ แนะนำโซลูชันแบบ polling โดยใช้ฟีเจอร์ FOR UPDATE SKIP LOCKED
ของ PostgreSQL แนวทางการตรวจสอบ WAL (Write-Ahead Log) ก็ได้รับความสนใจเช่นกันในฐานะวิธีการตรวจจับการเปลี่ยนแปลงฐานข้อมูลโดยไม่มีปัญหาการล็อก
หมายเหตุ: การตรวจสอบ WAL เกี่ยวข้องกับการดูล็อกธุรกรรมของ PostgreSQL เพื่อหาการเปลี่ยนแปลง ให้วิธีการตอบสนองต่อการอัปเดตฐานข้อมูลโดยไม่ใช้ LISTEN/NOTIFY
วิธีแก้ปัญหาทางเลือกที่มีการหารือ:
- แนวทางการ Polling: การใช้
FOR UPDATE SKIP LOCKED
ร่วมกับ exponential backoff - Message queues: NATS , Redis หรือ Kafka สำหรับการดำเนินงาน pub-sub
- การตรวจสอب WAL: การฟังการเปลี่ยนแปลงใน PostgreSQL Write-Ahead Log
- การติดตามในชั้น Application: การย้ายตรรกะการแจ้งเตือนออกจากฐานข้อมูล
- รูปแบบ Transactional outbox: การประมวลผลการแจ้งเตือนแยกต่างหากหลังจาก commit
บทเรียนสำหรับสถาปัตยกรรมฐานข้อมูล
เหตุการณ์นี้เน้นย้ำถึงปัญหาที่กว้างขึ้นในการพัฒนาซอฟต์แวร์สมัยใหม่: การล่อลวงให้ใช้ PostgreSQL เป็นมีดสวิสสำหรับความต้องการข้อมูลทั้งหมด แม้ว่า PostgreSQL จะมีความหลากหลายอย่างเหลือเชื่อ แต่การผลักดันให้เกินกว่ากรณีการใช้งานที่เหมาะสมสามารถนำไปสู่คอขวดที่ไม่คาดคิดได้
การอภิปรายของชุมชนเผยให้เห็นว่านักพัฒนาหลายคนได้พบปัญหาที่คล้ายกันกับฟีเจอร์อื่นๆ ของ PostgreSQL เช่น triggers และ row-level security ภายใต้โหลดสูง ฉันทามติดูเหมือนจะเป็นว่าแม้ฟีเจอร์เหล่านี้จะทำงานได้ดีสำหรับโหลดปานกลาง แต่พวกมันไม่ได้ขยายตัวแบบเชิงเส้นกับการใช้งานพร้อมกันที่เพิ่มขึ้น
ฐานข้อมูลมีไว้สำหรับข้อมูล ข้อมูลเข้าไปและข้อมูลออกมา แต่ข้อมูลไม่ได้มีสิทธิ์ตัดสินใจว่าจะเกิดอะไรขึ้นต่อไปโดยอิงจากตัวมันเอง นั่นคือสิ่งที่โค้ดแอปพลิเคชันมีไว้สำหรับ
สิ่งสำคัญที่ได้เรียนรู้คือความสำคัญของการทดสอบโหลดและการเข้าใจผลกระทบทางสถาปัตยกรรมของฟีเจอร์ฐานข้อมูลก่อนที่จะนำไปใช้ในการผลิต สิ่งที่ทำงานได้อย่างสมบูรณ์แบบสำหรับการดำเนินการหลายพันครั้งอาจล้มเหลวอย่างสิ้นเชิงที่หลายแสนครั้ง
การก้าวไปข้างหน้า
สำหรับนักพัฒนาที่ใช้ LISTEN/NOTIFY อยู่ในปัจจุบัน นี่ไม่ได้หมายถึงการตื่นตระหนกทันที ฟีเจอร์นี้ทำงานได้ดีสำหรับแอปพลิเคชันส่วนใหญ่ที่มีโหลดปานกลาง อย่างไรก็ตาม คุ้มค่าที่จะพิจารณาทางเลือกอื่นหากคุณกำลังวางแผนสำหรับการเติบโตที่สำคัญหรือประสบปัญหาประสิทธิภาพอยู่แล้ว
เหตุการณ์นี้ยังแสดงให้เห็นถึงคุณค่าของการตรวจสอบและการบันทึกที่เหมาะสม Recall.ai สามารถระบุประเภทการล็อกเฉพาะที่ทำให้เกิดปัญหาได้เฉพาะหลังจากเปิดใช้งานการบันทึกการล็อกโดยละเอียด ซึ่งช่วยให้พวกเขาติดตามปัญหากลับไปยังฟีเจอร์ LISTEN/NOTIFY
กรณีนี้เป็นเครื่องเตือนใจว่าแม้แต่ระบบฐานข้อมูลที่เป็นผู้ใหญ่และได้รับการยกย่องเช่น PostgreSQL ก็มีข้อจำกัดในการขยายตัวในที่ที่ไม่คาดคิด การป้องกันที่ดีที่สุดคือการทดสอบอย่างละเอียด การตรวจสอบที่เหมาะสม และการมีแผนการย้ายข้อมูลพร้อมเมื่อคุณถึงข้อจำกัดเหล่านั้น