วิธีในการป้องกันคิวรีไม่ให้รอการล็อกระดับตาราง


10

เราพบปัญหาหลังจากย้ายฐานข้อมูลของลูกค้าไปยังเซิร์ฟเวอร์เพิ่มเติม สิ่งนี้ควรมีผลในเชิงบวกต่อประสิทธิภาพของไซต์ แต่มีปัญหากับการล็อคตารางใน MyISAM (ฉันเคยได้ยินการใช้ InnoDB แทน MyISAM แต่เราไม่สามารถเปลี่ยนเครื่องยนต์ได้ในอนาคตอันใกล้)
เราสามารถตรวจสอบมันไปยังแบบสอบถามการปรับปรุงซึ่งจะดำเนินการเมื่อผู้ดูแลเปิดใช้งานความคิดเห็นในบทความ นี่คือกระบวนการ:

  • มีการประมวลผลการอัพเดตเคียวรี SET status = 1 WHERE id = 5(ตั้งค่าดัชนีแล้ว)
  • ไฟล์แคชของหน้าจะถูกลบ

เมื่อมาถึงจุดนี้ทั้งหน้าจะช้า ฐานข้อมูลไม่ว่างเป็นเวลาหลายนาที ฉันเรียก processlist ไม่กี่ครั้งและเห็นประมาณ 60 รายการที่แตกต่างกันการเลือกคำสั่งซึ่งทุกคนในรัฐรอล็อคระดับตาราง

1. ฉันไม่ได้ยกเลิกการยืนยันว่าเหตุใดการอัปเดตนี้ในตารางarticle_commentsอาจส่งผลกระทบต่อข้อความเลือกสำหรับตารางarticleเพื่อรอการล็อกระดับตาราง ในรายการกระบวนการแบบสอบถามที่รอเกือบทั้งหมดมาจากตารางนี้ ฉันได้อ่านเกี่ยวกับความจริงที่ว่าการปรับปรุง / การแทรกนั้นเป็นที่ต้องการของการเลือกและสิ่งนี้อาจทำให้เกิดปัญหาดังกล่าวได้ แต่ตัวบทความในตารางไม่ได้รับการอัพเดตเมื่อความคิดเห็นเปิดใช้งานดังนั้นการเลือกไม่ควรรอ ฉันผิดพลาดหรือไม่
2. มีอะไรอีกบ้างที่นอกเหนือจากการเปลี่ยนเป็น InnoDB เพื่อป้องกันพฤติกรรมนี้หรืออย่างน้อยก็เพื่อให้ได้สมดุลที่ดีขึ้น? ฉันหงุดหงิดมากเกี่ยวกับความจริงที่ว่าปัญหานี้ไม่ปรากฏขึ้นก่อนที่จะย้ายฐานข้อมูลไปยังเซิร์ฟเวอร์ใหม่ ฉันเดาว่ามีการกำหนดค่าผิดพลาดอยู่บ้าง แต่ฉันไม่รู้วิธีระบุตัวตน


1
เปิดใช้งานการบันทึกทั่วไปและดูคำสั่ง JOIN ระหว่างตารางเหล่านี้ เมื่อคุณเลือกมันจะสร้าง READ LOCK โดยนัย เนื่องจาก MYISAM ไม่รองรับการล็อค ROW LEVEL จึงล็อคที่ระดับโต๊ะ อาจเป็นกรณีที่การล็อกนี้เกิดขึ้นบนเซิร์ฟเวอร์เก่า แต่ไม่มีใครดู เปรียบเทียบบรรทัด my.cnf ของคุณเพื่อหาบรรทัดระหว่างโฮสต์และโดยเฉพาะอย่างยิ่งตรวจสอบให้แน่ใจว่า key_buffer ของคุณได้รับการปรับอย่างเหมาะสม
randomx

เรามีปัญหาด้านประสิทธิภาพอื่น ๆ หลายประการบนเซิร์ฟเวอร์เก่าและมักจะดูรายการกระบวนการ มีกระบวนการนอนหลับเป็นส่วนใหญ่ แต่เราไม่เคยสังเกตเห็นคนรอ (ฉันเห็นข้อมูลนี้โดยทั่วไปเป็นครั้งแรกในเซิร์ฟเวอร์ใหม่นี้) เพื่อนของฉันคัดลอก my.cnf เก่าและปรับค่าไปยังฮาร์ดแวร์ใหม่ที่มีอยู่ แต่ไม่มีรายการจำนวนมาก ฉันยังเปรียบเทียบผลลัพธ์ของ "SHOW VARIABLES" แต่ไม่ทราบว่าจะต้องดูอะไร เราจะตรวจสอบ keybuffer อีกครั้งในวันพรุ่งนี้ขอบคุณสำหรับความคิดเห็นของคุณ
32bitfloat

เราเพิ่งมีปัญหาที่คล้ายกัน ในขั้นต้นของเราถูกกำหนดให้key_buffer_size 1GBการเพิ่มนั้นเพื่อ10GBลดปัญหา
Haluk

@ Rick James ขอบคุณ วันนี้คุณช่วยฉันปัญหามากมาย คุณมีรายการความปรารถนาใน Amazon หรือที่อื่น ๆ ? :) ฉันตั้งค่า query_cache_limit เป็น 1024 ตอนนี้ไม่มีปัญหาการล็อค ฉันทำมันในตัวแปรตอนแรกจากไคลเอนต์ mysql ตั้งค่า global query_cache_limit = 1024; ตอนนี้ฉันจะเขียนถึง my.cnf วิธีแก้ปัญหานี้ทำให้ฉันมีเวลาในการวางแผนการย้ายถิ่นของ Innodb โดยไม่ต้องเครียดดังนั้นขอบคุณ

คำตอบ:


8

MyISAM Storage Engine นั้นมีชื่อเสียงในด้านการล็อคตารางเต็มรูปแบบสำหรับ DML ใด ๆ (INSERTs, UPDATEs, DELETEs) InnoDB จะแก้ไขปัญหานี้ในระยะยาวอย่างแน่นอน

ฉันเขียนเกี่ยวกับข้อดีข้อเสียของการใช้ MyISAM กับ InnoDB

เกี่ยวกับคำถามปัจจุบันของคุณนี่เป็นสถานการณ์ที่เป็นไปได้:

  • articleและarticle_commentsเป็นตาราง MyISAM
  • article_commentsมีดัชนีตั้งแต่หนึ่งดัชนีขึ้นไปพร้อมstatusคอลัมน์
  • การอัพเดตหน้าดัชนีสำหรับarticle_commentsถูกแคชใน MyISAM Key Buffer (ขนาดตามkey_buffer_size ) ทำให้หน้าดัชนีเก่าออกจาก MyISAM Key Buffer
  • คุณมีคิวรี SELECT ที่ดำเนินการเข้าร่วมระหว่างarticleและarticle_comments

ในสถานการณ์ที่แนะนำของฉัน SELECT กับarticleตารางสามารถหยุดการอนุญาตให้เขียนได้เนื่องจากต้องรอarticle_commentsเป็นอิสระจาก DML ใด ๆ (ในกรณีนี้และUPDATE)


ขอบคุณสำหรับคำตอบ (และลิงก์) สถานการณ์ของคุณเป็นจริง ฉันไม่ได้ตระหนักว่าส่วนใหญ่ของบทความที่เลือกเข้าร่วมแน่นอนแสดงความคิดเห็นตาราง (หรือในคำอื่น ๆ เห็นคำสั่งที่ไม่สมบูรณ์ในรายการกระบวนการของ phpmyadmin) คุณรู้วิธีแก้ปัญหาระยะสั้นเพื่อป้องกันการรอคำสั่งหลายรายการ? ฉันได้ลองด้วย "UPDATE LOW_PRIORITY" ในคำสั่งเฉพาะ แต่ไม่ได้ทำการเปลี่ยนแปลงที่เห็นได้ชัดเจน เราจะเปลี่ยนเป็น Innodb อย่างแท้จริงในอนาคต แต่ฉันสงสัยว่าจะมีวิธีการปรับปรุงให้ดีขึ้นหรือไม่
32bitfloat

ทางออกที่ดีที่สุด: แปลงตารางเป็น InnoDB ดูโพสต์ของฉันdba.stackexchange.com/a/9422/877เกี่ยวกับวิธีการแปลง MyISAM ทุกอย่างเป็น InnoDB
RolandoMySQLDBA

7

เมื่อมาถึงจุดนี้ทั้งหน้าจะช้า ฐานข้อมูลไม่ว่างเป็นเวลาหลายนาที

มีกลิ่นเหมือนคุณมี Query_cache ขนาดใหญ่ไหม?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

สำหรับระบบการผลิตที่มีการเขียนจำนวนมากคุณอาจปิด query_cache

รายการทั้งหมดใน query_cache สำหรับตารางที่กำหนดจะถูกลบทิ้งเมื่อการเขียนใด ๆเกิดขึ้นกับตารางนั้น ยิ่ง QC ยิ่งใหญ่ก็ยิ่งทำงานนี้ช้าลง

MyISAM ใช้การล็อค "ระดับตาราง" การอ่านและเขียนไม่สามารถเกิดขึ้นได้ในเวลาเดียวกัน (ในตารางเดียวกัน) ดิบ แต่มีประสิทธิภาพ


1
ก็ใช่ เรามีแคชประมาณ 64M ขอบคุณสำหรับข้อมูลนี้ซึ่งเป็นเรื่องใหม่สำหรับฉันอย่างไรก็ตามเรามีค่าเดียวกันบนเซิร์ฟเวอร์เก่าที่เราไม่ได้สังเกตเห็น tablelockings เราได้เริ่มย้ายไปที่ InnoDB แล้ว แต่ความจริงข้อนี้ยังคงเป็นเรื่องลึกลับ ...
32bitfloat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.