한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

คู่มือเกมแลค › L12 ฐานข้อมูล

คนแห่ล็อกอินและคิวรี N+1 Login storm, N+1 queries

ID สาเหตุ db-login-storm · ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)

เปิดการ์ดในฉบับหลักที่มีภาพและการทดลอง →

ถ้าการโหลดตัวละครหนึ่งตัวต้องดึงข้อมูลแยกกันหลายสิบครั้ง ผู้เล่นหลายหมื่นคนที่ล็อกอินพร้อมกันจะกลายเป็นคิวรีหลายล้านคิวรี

ทำไม ตอนโหลดตัวละคร ดึงไอเทม สกิล และเควสต์แยกกันทีละอย่าง → ผลคือ หลังปิดปรับปรุงใหม่ ๆ คนล็อกอินพร้อมกันจนคิวรีพุ่ง → บนหน้าจอ ล็อกอินโหลดไม่จบ, การเซฟของคนที่กำลังเล่นอยู่ก็ล่าช้าไปด้วย

อาการ
เข้าเกมไม่ได้/โหลดไม่จบ, อินพุตดีเลย์
ปัจจัย
การหยุดชะงัก, ความหน่วง
ใครเจอ
ทั้งเซิร์ฟเวอร์
เกิดเมื่อไร
หลังล็อกอิน/หลังปิดปรับปรุง
ผู้รับผิดชอบ
ผู้รับผิดชอบหลัก พัฒนาเซิร์ฟเวอร์ (ทีมพัฒนาเกม) · ร่วมกับ อินฟรา DB (ทีมอินฟรา)
งานฝั่งทีมพัฒนาเกม
ดึงข้อมูลรวมทีเดียว, คิวล็อกอิน, แคช, ตรวจจำนวนคิวรีที่เกิดจาก lazy loading ของ ORM
งานฝั่งทีมอินฟรา
จัดอันดับคิวรีที่ถูกเรียกบ่อยแล้วแชร์, มอนิเตอร์จำนวนคิวรีและจำนวน connection ช่วงล็อกอินหลังปิดปรับปรุง
บนกราฟ
พุ่งทันทีหลังเปิดเซิร์ฟ/ปิดปรับปรุง · จำนวนคิวรีต่อวินาทีของ DB, จำนวนการล็อกอิน
จุดที่ต้องดู
วางจำนวนการล็อกอินหลังปิดปรับปรุงซ้อนกับจำนวนคิวรีต่อวินาทีของ DB (MySQL คือค่าที่เพิ่มขึ้นของ Questions) แล้วคำนวณจำนวนคิวรีต่อการล็อกอินหนึ่งครั้ง คิวรีที่ถูกเรียกบ่อยที่สุดดึงได้จาก COUNT_STAR ใน events_statements_summary_by_digest ของ MySQL และ calls ใน pg_stat_statements ของ PostgreSQL
สัญญาณว่าใช่
การล็อกอินหนึ่งครั้งใช้คิวรีหลายสิบคิวรี และคิวรีอันดับต้น ๆ เป็นคิวรีสั้น ๆ หน้าตาเดียวกันที่ดึงข้อมูลด้วย ID ตัวละครตัวเดียว ถ้าจำนวนคิวรีต่อการล็อกอินเพิ่มขึ้นหลังแพตช์ แพตช์นั้นคือจุดเริ่มต้น
สัญญาณว่าไม่ใช่
จำนวนคิวรีต่อการล็อกอินน้อยแต่แต่ละคิวรีช้า: น่าจะเป็น cold cache (db-cold-cache) หรืออินเด็กซ์ (db-no-index)
วิธีตรวจ
ใช้เครื่องมือฝั่งอินฟรา (ไม่ต้องใช้โค้ดเกม)
รายละเอียดเพิ่มเติม
lazy loading ของ ORM (ไลบรารีที่สร้างคิวรี DB ให้) สร้างคิวรีแบบนี้โดยที่นักพัฒนาเองก็ไม่รู้ตัว บนเซิร์ฟเวอร์ dev มีตัวละครไม่กี่ตัวจึงไม่เห็นผล แล้วมาโผล่ครั้งแรกตอนคนล็อกอินพร้อมกันบนเซิร์ฟเวอร์ live

แหล่งอ้างอิง

  1. Efficient Querying .NET
    lazy loading ของ ORM ทำให้เกิดปัญหา N+1 ที่ส่งคิวรีเพิ่มอีกหนึ่งครั้งต่อทุกรายการ ทำให้ประสิทธิภาพตกมาก, แนะนำให้โหลดรวมทีเดียว (eager loading)
  2. pg_stat_statements — track statistics of SQL planning and execution PostgreSQL
    รวบรวมจำนวนครั้งที่รัน (calls) และเวลารันรวมของแต่ละคำสั่ง เพื่อจัดอันดับคิวรีที่ถูกเรียกบ่อย
  3. Performance Schema Statement Digests and Sampling MySQL
    events_statements_summary_by_digest จัดกลุ่มคิวรีหน้าตาเดียวกันแล้วสรุปจำนวนครั้งและเวลา
  4. Statement Summary Tables MySQL
    COUNT_STAR (จำนวนครั้งที่รัน) และ SUM_TIMER_WAIT (เวลารวม) ในตารางสรุป
  5. Server Status Variables MySQL
    Questions: จำนวนคำสั่งที่ไคลเอนต์ส่งมา

สาเหตุที่ควรดูประกอบ

ชั้นเดียวกัน: L12 ฐานข้อมูล

สาเหตุจากชั้นอื่นที่ทำให้เกิดอาการเดียวกัน (เข้าเกมไม่ได้/โหลดไม่จบ)

ดูการ์ดในฉบับหลักที่มีภาพและการทดลอง