SQLite ล็อกไม่ไหลลื่น? Jellyfin แก้เกมด้วยกลยุทธ์ล็อกอัจฉริยะ

ลองจินตนาการว่าคุณกำลังใช้แอปที่เก็บข้อมูลด้วย SQLite ซึ่งเป็นฐานข้อมูลที่เบาและทรงพลัง แต่จู่ๆ แอปก็แครชโดยไม่มีเหตุผลชัดเจน ทั้งที่คุณแค่สั่งให้มันเขียนข้อมูลเพิ่ม… นี่คือปัญหาที่ Jellyfin เจอมาอย่างยาวนาน และตอนนี้พวกเขาได้แชร์วิธีแก้ไขที่น่าสนใจสำหรับนักพัฒนา EF Core ทุกคน

SQLite: ฐานข้อมูลที่ดีแต่มีข้อจำกัด SQLite เป็นฐานข้อมูลแบบไฟล์เดียวที่ทำงานในแอปโดยตรง ไม่ต้องพึ่งเซิร์ฟเวอร์ภายนอก แต่ข้อจำกัดคือมันไม่เหมาะกับการเขียนข้อมูลพร้อมกันหลายๆ ครั้ง เพราะมันล็อกไฟล์ไว้ขณะเขียน ทำให้เกิดปัญหา “database is locked” ได้ง่าย โดยเฉพาะในแอปที่มีการเขียนข้อมูลแบบขนาน

WAL (Write-Ahead Logging): ตัวช่วยแต่ไม่ใช่คำตอบ แม้ SQLite จะมีโหมด WAL ที่ช่วยให้เขียนข้อมูลแบบขนานได้บ้าง แต่ก็ยังมีสถานการณ์ที่ WAL ไม่สามารถป้องกันการล็อกได้ทั้งหมด โดยเฉพาะเมื่อมีธุรกรรม (transaction) ที่ยาวหรือซับซ้อน

Jellyfin เจอปัญหาเต็มๆ ก่อนเวอร์ชัน 10.11 Jellyfin มีบั๊กที่ทำให้เกิดการ overscheduling งานสแกนไลบรารี ส่งผลให้ SQLite ถูกถล่มด้วยคำสั่งเขียนหลายพันคำสั่งพร้อมกัน จนระบบ retry ก็เอาไม่อยู่ ทำให้แอปแครชบ่อยโดยไม่มีสาเหตุแน่ชัด

EF Core + Interceptor: ทางออกที่ Jellyfin เลือกใช้ เมื่อ Jellyfin ย้ายมาใช้ EF Core เต็มรูปแบบ พวกเขาใช้ “Interceptor” เพื่อควบคุมการเขียนข้อมูลแบบขนาน โดยมี 3 กลยุทธ์หลัก:
1️⃣ No-Lock: ไม่ทำอะไรเลย ใช้ในกรณีทั่วไปที่ไม่มีปัญหา
2️⃣ Optimistic Locking: ลองเขียน ถ้าไม่สำเร็จค่อย retry
3️⃣ Pessimistic Locking: ล็อกทุกครั้งก่อนเขียน เพื่อป้องกันปัญหาโดยเด็ดขาด

Polly: ตัวช่วยในการ retry Jellyfin ใช้ไลบรารี Polly เพื่อจัดการ retry อย่างชาญฉลาด โดยจะ retry เฉพาะคำสั่งที่ล้มเหลวจากการล็อกเท่านั้น

อนาคต: Smart Locking ทีม Jellyfin กำลังพิจารณาการผสมผสานระหว่าง Optimistic และ Pessimistic เพื่อให้ได้ทั้งความเร็วและความเสถียร

SQLite มีข้อจำกัดด้าน concurrency
ไม่สามารถเขียนข้อมูลหลายคำสั่งพร้อมกันได้ดี

WAL ช่วยได้บางส่วน
แต่ยังมีโอกาสเกิดการล็อกเมื่อมีธุรกรรมซับซ้อน

Jellyfin เจอปัญหาแครชจากการเขียนขนาน
เกิดจากบั๊ก overscheduling และธุรกรรมที่ไม่เหมาะสม

EF Core Interceptor คือทางออก
ใช้ควบคุมการเขียนข้อมูลแบบขนานอย่างมีประสิทธิภาพ

มี 3 กลยุทธ์การล็อก
No-Lock, Optimistic Locking, Pessimistic Locking

Polly ใช้สำหรับ retry อย่างชาญฉลาด
ลดโอกาสแครชจากการล็อกซ้ำซ้อน

Smart Locking อาจเป็นอนาคต
ผสมข้อดีของทั้งสองแนวทางเพื่อประสิทธิภาพสูงสุด

ธุรกรรมที่ยาวหรือไม่เหมาะสมอาจทำให้ระบบล่ม
SQLite ไม่สามารถจัดการกับคำสั่งเขียนจำนวนมากพร้อมกันได้ดี

การเขียนขนานโดยไม่มีการควบคุมเสี่ยงต่อการแครช
แอปอาจล้มเหลวทันทีหากไม่มีระบบ retry หรือ locking ที่ดี

WAL ไม่ใช่คำตอบสุดท้าย
ยังมีสถานการณ์ที่ WAL ไม่สามารถป้องกันการล็อกได้

https://jellyfin.org/posts/SQLite-locking/
🧠 SQLite ล็อกไม่ไหลลื่น? Jellyfin แก้เกมด้วยกลยุทธ์ล็อกอัจฉริยะ ลองจินตนาการว่าคุณกำลังใช้แอปที่เก็บข้อมูลด้วย SQLite ซึ่งเป็นฐานข้อมูลที่เบาและทรงพลัง แต่จู่ๆ แอปก็แครชโดยไม่มีเหตุผลชัดเจน ทั้งที่คุณแค่สั่งให้มันเขียนข้อมูลเพิ่ม… นี่คือปัญหาที่ Jellyfin เจอมาอย่างยาวนาน และตอนนี้พวกเขาได้แชร์วิธีแก้ไขที่น่าสนใจสำหรับนักพัฒนา EF Core ทุกคน 📂 SQLite: ฐานข้อมูลที่ดีแต่มีข้อจำกัด SQLite เป็นฐานข้อมูลแบบไฟล์เดียวที่ทำงานในแอปโดยตรง ไม่ต้องพึ่งเซิร์ฟเวอร์ภายนอก แต่ข้อจำกัดคือมันไม่เหมาะกับการเขียนข้อมูลพร้อมกันหลายๆ ครั้ง เพราะมันล็อกไฟล์ไว้ขณะเขียน ทำให้เกิดปัญหา “database is locked” ได้ง่าย โดยเฉพาะในแอปที่มีการเขียนข้อมูลแบบขนาน 📝 WAL (Write-Ahead Logging): ตัวช่วยแต่ไม่ใช่คำตอบ แม้ SQLite จะมีโหมด WAL ที่ช่วยให้เขียนข้อมูลแบบขนานได้บ้าง แต่ก็ยังมีสถานการณ์ที่ WAL ไม่สามารถป้องกันการล็อกได้ทั้งหมด โดยเฉพาะเมื่อมีธุรกรรม (transaction) ที่ยาวหรือซับซ้อน 💥 Jellyfin เจอปัญหาเต็มๆ ก่อนเวอร์ชัน 10.11 Jellyfin มีบั๊กที่ทำให้เกิดการ overscheduling งานสแกนไลบรารี ส่งผลให้ SQLite ถูกถล่มด้วยคำสั่งเขียนหลายพันคำสั่งพร้อมกัน จนระบบ retry ก็เอาไม่อยู่ ทำให้แอปแครชบ่อยโดยไม่มีสาเหตุแน่ชัด 🔧 EF Core + Interceptor: ทางออกที่ Jellyfin เลือกใช้ เมื่อ Jellyfin ย้ายมาใช้ EF Core เต็มรูปแบบ พวกเขาใช้ “Interceptor” เพื่อควบคุมการเขียนข้อมูลแบบขนาน โดยมี 3 กลยุทธ์หลัก: 1️⃣ No-Lock: ไม่ทำอะไรเลย ใช้ในกรณีทั่วไปที่ไม่มีปัญหา 2️⃣ Optimistic Locking: ลองเขียน ถ้าไม่สำเร็จค่อย retry 3️⃣ Pessimistic Locking: ล็อกทุกครั้งก่อนเขียน เพื่อป้องกันปัญหาโดยเด็ดขาด 🧠 Polly: ตัวช่วยในการ retry Jellyfin ใช้ไลบรารี Polly เพื่อจัดการ retry อย่างชาญฉลาด โดยจะ retry เฉพาะคำสั่งที่ล้มเหลวจากการล็อกเท่านั้น 🚀 อนาคต: Smart Locking ทีม Jellyfin กำลังพิจารณาการผสมผสานระหว่าง Optimistic และ Pessimistic เพื่อให้ได้ทั้งความเร็วและความเสถียร ✅ SQLite มีข้อจำกัดด้าน concurrency ➡️ ไม่สามารถเขียนข้อมูลหลายคำสั่งพร้อมกันได้ดี ✅ WAL ช่วยได้บางส่วน ➡️ แต่ยังมีโอกาสเกิดการล็อกเมื่อมีธุรกรรมซับซ้อน ✅ Jellyfin เจอปัญหาแครชจากการเขียนขนาน ➡️ เกิดจากบั๊ก overscheduling และธุรกรรมที่ไม่เหมาะสม ✅ EF Core Interceptor คือทางออก ➡️ ใช้ควบคุมการเขียนข้อมูลแบบขนานอย่างมีประสิทธิภาพ ✅ มี 3 กลยุทธ์การล็อก ➡️ No-Lock, Optimistic Locking, Pessimistic Locking ✅ Polly ใช้สำหรับ retry อย่างชาญฉลาด ➡️ ลดโอกาสแครชจากการล็อกซ้ำซ้อน ✅ Smart Locking อาจเป็นอนาคต ➡️ ผสมข้อดีของทั้งสองแนวทางเพื่อประสิทธิภาพสูงสุด ‼️ ธุรกรรมที่ยาวหรือไม่เหมาะสมอาจทำให้ระบบล่ม ⛔ SQLite ไม่สามารถจัดการกับคำสั่งเขียนจำนวนมากพร้อมกันได้ดี ‼️ การเขียนขนานโดยไม่มีการควบคุมเสี่ยงต่อการแครช ⛔ แอปอาจล้มเหลวทันทีหากไม่มีระบบ retry หรือ locking ที่ดี ‼️ WAL ไม่ใช่คำตอบสุดท้าย ⛔ ยังมีสถานการณ์ที่ WAL ไม่สามารถป้องกันการล็อกได้ https://jellyfin.org/posts/SQLite-locking/
JELLYFIN.ORG
SQLite concurrency and why you should care about it | Jellyfin
SQLite is a powerful database engine, but due to its design, it has limitations that should not be overlooked.
0 Comments 0 Shares 65 Views 0 Reviews