เป็นไปได้ไหมที่ทำให้ MySQL ใช้มากกว่าหนึ่งคอร์?


131

ฉันได้รับการนำเสนอด้วยเซิร์ฟเวอร์ MySQL เฉพาะที่ไม่เคยใช้มากกว่าหนึ่งคอร์ ฉันเป็นนักพัฒนามากกว่า DBA สำหรับ MySQL ดังนั้นต้องการความช่วยเหลือ

ติดตั้ง

เซิร์ฟเวอร์ค่อนข้างหนักด้วยการโหลดประเภท OLAP / DataWarehouse (DW):

  • หลัก: 96GB RAM, 8 คอร์ + RAID 10 อาเรย์เดียว
  • ทดสอบ: RAM 32GB พร้อม 4 คอร์
  • ฐานข้อมูลที่ใหญ่ที่สุดคือ 540 GB, รวมอยู่ที่ประมาณ 1.1TB และส่วนใหญ่เป็นตาราง InnoDB
  • Solaris 10 Intel-64
  • MySQL 5.5.x

หมายเหตุ: ฐานข้อมูลที่ใหญ่ที่สุดคือหนึ่งที่จำลองแบบจากเซิร์ฟเวอร์ OLTP DR และ DW จะถูกโหลดจากสิ่งนี้ มันไม่ใช่ DW เต็มรูปแบบ: เมื่อ 6 เดือนถึง 6 สัปดาห์ดังนั้นมันจึงเล็กกว่า OLTP DB

การสังเกตบนเซิร์ฟเวอร์ทดสอบ

  • 3 การเชื่อมต่อแยก
  • แต่ละคนมีพร้อมกัน (และแตกต่างกัน) ALTER TABLE...DROP KEY...ADD INDEX
  • 3 ตารางมีแถว 2.5, 3.8 และ 4.5 ​​ล้าน
  • การใช้งาน CPU สูงถึง 25% (หนึ่งคอร์มีขนาดสูงสุด) และไม่สูงกว่า
  • 3 ALTERs ใช้เวลา 12-25 นาที (Single ที่เล็กที่สุดใช้เวลา 4.5)

คำถาม

  1. จำเป็นต้องมีการตั้งค่าหรือแพทช์ใดเพื่ออนุญาตให้ใช้มากกว่าหนึ่งคอร์?
    นั่นคือทำไม MySQL ไม่ใช้คอร์ทั้งหมดที่มีอยู่ (เช่น RDBMS อื่น ๆ )
  2. มันเป็นผลมาจากการจำลองแบบ?

บันทึกอื่น ๆ

  • ฉันเข้าใจความแตกต่างระหว่าง RDBMS "thread" และ OS "thread"
  • ฉันไม่ได้ถามเกี่ยวกับการขนานใด ๆ
  • ตัวแปรระบบบางส่วนสำหรับ InnoDB และเธรดเป็นแบบย่อย
    (มองหาการชนะอย่างรวดเร็ว)
  • ระยะสั้นฉันไม่สามารถเปลี่ยนเค้าโครงดิสก์
  • ระบบปฏิบัติการสามารถปรับแต่งถ้าจำเป็น
  • ALTER TABLE เดียวบนตารางที่เล็กที่สุดใช้เวลา 4.5 นาที (IMO ที่น่าตกใจ)

แก้ไข 1

  • innodb_thread_concurrency ถูกตั้งค่าเป็น 8 บนทั้งคู่ ใช่มันผิด แต่จะไม่ทำให้ MySQL ใช้หลายคอร์
  • innodb_buffer_pool_size คือ 80GB สำหรับไฟล์หลัก, 10GB สำหรับการทดสอบ (อินสแตนซ์อื่นปิดตัวลง) ไม่เป็นไรตอนนี้
  • innodb_file_per_table = ON

แก้ไข 2

  • innodb_flush_log_at_trx_commit = 2
  • innodb_use_sys_malloc = ON
  • innodb_flush_method ควรเป็น O_DIRECT (แต่ SHOW VARIABLES ไม่แสดงสิ่งนี้)
  • innodb_doublewrite = OFF
  • ระบบไฟล์ = ZFS (และระบบดูแลระบบของฉันพบสิ่งนี้: http://blogs.oracle.com/realneel/entry/mysql_innodb_zfs_best_practices )

ทดสอบ

  • innodb_flush_method ไม่แสดงเป็น O_DIRECT เมื่อควรจะเป็น
  • จะทำตามการตั้งค่าของ RolandoMySQLDBA

แจ้งให้เราทราบหากฉันพลาดอะไรสำคัญไป

ไชโย

ปรับปรุง

เปลี่ยน innodb_flush_method + 3 x การตั้งค่าเธรดในคำตอบของ RolandoMySQLDBA
ผล:> 1 แกนที่ใช้สำหรับการทดสอบ = ผลบวก


@Dtest: innodb_file_per_table = ON SHOW ENGINE INNODB STATUS \ G เป็น command line เท่านั้น?
GBN

@Dtest: ผมได้รับการส่งออกใน SQLyog ไม่ได้และจะต้องถามคนที่จะทำงานนี้จากบรรทัดคำสั่ง
GBN

1
webyog.com/forums/index.php?showtopic=1290\Gควรจะทำงานได้โดยไม่ต้อง นอกจากนี้ฉันคิดว่าSHOW INNODB STATUSเลิกใช้ในSHOW ENGINE INNODB STATUS5.5 (ฉันได้รับข้อผิดพลาดในการเรียกใช้อดีตในบรรทัดคำสั่ง
Derek Downey

1
ในขณะที่คำตอบอื่น ๆ ทั้งหมดเป็นสิ่งที่ดีเนื่องจากคุณเป็นนักพัฒนาซอฟต์แวร์ฉันขอแนะนำให้ดูที่ Shard Query code.google.com/p/shard-queryมันอาจช่วยคุณได้โดยเฉพาะในสภาพแวดล้อมของคลังข้อมูล
Jonathan

ขอบคุณมันเป็นหนึ่งในตัวเลือกที่เราคิด I = m ก็รับบท DBA ด้วยเช่นกัน
GBN

คำตอบ:


123

ที่จริงผมกล่าวถึง innodb_thread_concurrency กับผู้เชี่ยวชาญ MySQL ในการประชุม Percona สดนิวยอร์คกลับพฤษภาคม 2011

ฉันได้เรียนรู้สิ่งที่น่าแปลกใจ: แม้ว่าเอกสารจะดีที่สุดที่จะทิ้งไว้innodb_thread_concurrencyที่ 0 (การเกิดพร้อมกันที่ไม่มีที่สิ้นสุด) ด้วยวิธีนี้ InnoDB ตัดสินใจเปิดหมายเลขที่ดีที่สุดinnodb_concurrency_ticketsสำหรับการตั้งค่าอินสแตนซ์ MySQL ที่กำหนด

เมื่อคุณตั้งค่าinnodb_thread_concurrencyเป็น 0 คุณสามารถตั้งค่าinnodb_read_io_threadsและinnodb_write_io_threads(ทั้งตั้งแต่ MySQL 5.1.38) เป็นค่าสูงสุด 64 ซึ่งควรมีส่วนร่วมมากขึ้น


จะลองสิ่งนี้ ฉันกำลังจะตั้ง innodb_thread_concurrency เป็น 0 อย่างไรก็ตามขึ้นอยู่กับสิ่งที่ฉันได้อ่านด้วย
gbn

9
+1 สำหรับ innodb_thread_concurrency = 0
Randomx

3
@gbn - มาจาก # 1 ผู้ชายใน DBA.SE ขอบคุณเป็นผู้สนับสนุนความเชื่อมั่นและชื่นชมอย่างมาก ขอบคุณและยินดีต้อนรับ !!!
RolandoMySQLDBA

set global innodb_read_io_threads = 8 รหัสข้อผิดพลาด: 1238 ตัวแปร 'innodb_read_io_threads' เป็นตัวแปรแบบอ่านอย่างเดียว
wgq3g23g

2
@ wgq3g23g หากคุณกำลังทำ RDS ให้เปลี่ยนในกลุ่มพารามิเตอร์ DB และรีบูตอินสแตนซ์ หากคุณกำลังทำ EC2 หรือโลหะเปลือยให้เพิ่มตัวเลือกนั้นmy.cnfและรีสตาร์ท mysqld โปรด.
RolandoMySQLDBA

29

MySQL จะใช้หลายคอร์โดยอัตโนมัติดังนั้นโหลดของคุณ 25% จึงเป็นเรื่องบังเอิญ1หรือการกำหนดค่าผิดพลาดบนโซลาริส ฉันจะไม่หลอกจะทราบวิธีการปรับแต่ง Solaris แต่นี่เป็นบทความที่จะไปมากกว่าบางข้อมูลการปรับแต่ง Solaris เฉพาะ

หน้าการปรับแต่ง InnoDB ได้รับการยกเครื่องใน MySQL 5.5 ดังนั้นจึงมีข้อมูลที่ดีเช่นกัน จากเคล็ดลับ IOo ดิสก์ InnoDB :

หากเครื่องมือบนสุดของ Unix หรือตัวจัดการงานของ Windows แสดงว่าเปอร์เซ็นต์การใช้งาน CPU กับปริมาณงานของคุณน้อยกว่า 70% ปริมาณงานของคุณอาจเป็นภาระผูกพันของดิสก์ บางทีคุณอาจทำธุรกรรมมากเกินไปหรือบัฟเฟอร์พูลมีขนาดเล็กเกินไป การทำให้บัฟเฟอร์พูลใหญ่ขึ้นสามารถช่วยได้ แต่อย่าตั้งค่าเท่ากับหน่วยความจำฟิสิคัลมากกว่า 80%

สิ่งอื่น ๆ ที่ควรตรวจสอบ:

  • การเปลี่ยนinnodb_flush_methodเป็น O_DIRECT เป็นการทดสอบที่คุ้มค่า หากสิ่งนี้ช่วยได้คุณอาจต้องติดตั้งระบบไฟล์ด้วยforcedirectioตัวเลือก

  • เปลี่ยนinnodb_flush_log_at_trx_commitจาก 1 เป็น 0 (หากคุณไม่รังเกียจที่จะสูญเสียวินาทีสุดท้ายจากการชน mysql) หรือ 2 (ถ้าคุณไม่รังเกียจที่จะสูญเสียวินาทีที่สองใน OS crash)

  • ตรวจสอบค่าของinnodb_use_sys_malloc บทความนี้มีข้อมูลเพิ่มเติมเกี่ยวกับตัวแปร

    ในเวลานั้นไม่มีไลบรารีตัวจัดสรรหน่วยความจำที่ปรับสำหรับซีพียูแบบมัลติคอร์ ดังนั้น InnoDB จึงใช้ตัวจัดสรรหน่วยความจำของตัวเองในระบบย่อย mem ตัวจัดสรรนี้ได้รับการปกป้องโดย mutex เดี่ยวซึ่งอาจกลายเป็นคอขวด

    แต่มีข้อแม้บางส่วนที่ท้ายสุดของส่วนเกี่ยวกับความหมายของการเปิดตัวแปร (โดยค่าเริ่มต้นคือ 5.5)

    โปรดทราบว่าเมื่อตัวจัดสรรหน่วยความจำ InnoDB ถูกปิดใช้งาน InnoDB จะไม่สนใจค่าของพารามิเตอร์ innodb_additional_mem_pool_size

  • เป็นไปได้ว่าการจำลองแบบเป็นสาเหตุของปัญหา ฉันรู้ว่าคุณไม่ได้สนใจคู่ขนาน แต่มาจากคำอธิบายของบันทึกงานนี้ :

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

ในที่สุด InnoDB อาจไม่ใช่เอ็นจิ้นที่ดีที่สุดสำหรับการจัดเก็บข้อมูลเนื่องจากการดำเนินการบนดิสก์ที่เกิดขึ้น คุณอาจจะพิจารณาการเปลี่ยนแปลงตารางข้อมูลคลังสินค้า (s) ที่จะอัด MyISAM

1 โดยบังเอิญฉันหมายถึงมีคอขวดที่ป้องกันไม่ให้โหลดของคุณเพิ่มขึ้นสูงกว่า 25% แต่ไม่จำเป็นต้องเป็นปัญหาแบบ Single-Core


ขอบคุณ ส่วนการตั้งค่าถูกเพิ่มเข้าไปในคำถาม ปัญหาคือแบบสอบถามที่เข้มข้นหลายรายการโดยใช้คอร์เดียว: ยังไม่ได้ตั้งค่าหน่วยความจำหรือเธรด หัวข้อเพิ่มเติมยังคงทำงานบนแกนเดียวกัน
gbn

@gbn ขอบคุณสำหรับการปรับปรุงยังคงมองหา ฉันคิดว่ามันเป็น 'เรื่องบังเอิญ' ฉันสงสัยว่ามันเป็นปัญหาโซลาริสเท่านั้นหรือไม่ ( Developers.sun.com/solaris/articles/mysql_perf_tune.html ) แต่ไม่รู้เกี่ยวกับระบบนั้นมากนัก
Derek Downey

1
@Dtest: ฉันจะโยนบทความนั้นไปยังผู้ดูแลระบบ Solaris เกินไปบางสิ่งที่ดีมี
GBN

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

15

การเชื่อมต่อเดียวจะใช้แกนเดียวเท่านั้น (ตกลง InnoDB ใช้เธรดอื่นดังนั้นคอร์สำหรับการประมวลผล I / O บางตัว แต่ไม่สำคัญ)

คุณมี 3 ALTER ดังนั้นคุณไม่ได้ใช้มากกว่า 3 คอร์

อนิจจาไม่ใช่แม้แต่ PARTITION ที่ใช้หลายคอร์

จนกระทั่งเมื่อเร็ว ๆ นี้การเชื่อมต่อหลายรายการจะสูงสุดหลังจากแกนประมวลผล 4-8 คอร์ Percona's Xtradb (รวมอยู่ใน MariaDB) ใช้ประโยชน์ได้ดีกว่าหลายคอร์ แต่ยังคงมีเพียงหนึ่งต่อเธรดเท่านั้น พวกมันออกสูงสุดที่ประมาณ 32 แกน


(อัปเดตในปี 2558 :) การเชื่อมต่อที่หลากหลายด้วย 5.6 maxes out ที่ประมาณ 48 cores 5.7 สัญญาว่าจะดียิ่งขึ้น (ดังนั้นมาตรฐานของ Oracle กล่าว) แต่ก็ยังไม่มีการใช้หลายคอร์สำหรับการเชื่อมต่อเดียว
Rick James

Update (หลังจากไปที่ OpenWorld ของ Oracle): เวอร์ชันใหม่ 8.x จะไม่มีการขนานใด ๆ
Rick James

9

IMHO และในกรณีการใช้งานที่อธิบายไว้คุณจะไม่ใช้แกนมากกว่าหนึ่งแกน เหตุผลก็คือเวิร์กโหลดของคุณนั้นเป็น IO ที่ถูกผูกไว้ไม่ใช่ CPU ที่ถูกผูกไว้ เนื่องจากการเชื่อมต่อ 3 รายการของคุณกำลังสร้างดัชนีใหม่แต่ละรายการจำเป็นต้องอ่านทั้งตารางจากดิสก์: นี่คือสิ่งที่ต้องใช้เวลาไม่ใช่การคำนวณดัชนี


8

พิจารณาว่าคอขวดของคุณอาจเป็นประสิทธิภาพ IO ของระบบไฟล์ของคุณ

นอกเหนือจากการตั้งค่าที่แนะนำโดย @RolandoMySQLDBAฉันยังตั้งค่าการnoatimeเมานท์/etc/fstabสำหรับพาร์ติชันที่ถือไดเรกทอรีข้อมูล mysql ของฉัน ( /data01/mysqlในกรณีของฉันพร้อม/dev/sdb1ติดตั้ง/data01)

โดยค่าเริ่มต้น linux จะบันทึกเวลาในการเข้าถึงสำหรับการอ่านหรือเขียนดิสก์ทุกครั้งซึ่งมีผลเสียต่อประสิทธิภาพการทำงานของ IO โดยเฉพาะอย่างยิ่งสำหรับแอปพลิเคชัน IO ที่สูงเช่นฐานข้อมูล ซึ่งหมายความว่าแม้การอ่านข้อมูลจากไฟล์จะทำให้เกิดการเขียนลงดิสก์ ... WAT!

หากต้องการปิดใช้งานให้เพิ่มnoatimeตัวเลือกการเมานท์/etc/fstabสำหรับจุดเมานท์ที่ต้องการดังต่อไปนี้ (ตัวอย่างในกรณีของฉัน):

/dev/sdb1  /data01  ext4  defaults,noatime  0  2

จากนั้นติดตั้งพาร์ติชันใหม่:

mount -o,remount /data01

สิ่งนี้ควรเพิ่มประสิทธิภาพการอ่าน / เขียนของแอปพลิเคชันโดยใช้พาร์ติชันนั้น แต่ ... ไม่มีอะไรเต้นที่จะเก็บข้อมูลทั้งหมดของคุณไว้ในหน่วยความจำ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.