Có thể làm cho MySQL sử dụng nhiều hơn một lõi?


131

Tôi đã được giới thiệu một số máy chủ MySQL chuyên dụng không bao giờ sử dụng nhiều hơn một lõi. Tôi là nhà phát triển hơn DBA cho MySQL nên cần một số trợ giúp

Thiết lập

Các máy chủ khá nặng với tải loại OLAP / DataWarehouse (DW):

  • Chính: RAM 96GB, 8 lõi + mảng RAID 10 đơn
  • Kiểm tra: RAM 32 GB với 4 nhân
  • DB lớn nhất là 540 GB, tổng cộng là khoảng 1,1TB và chủ yếu là các bảng InnoDB
  • Solaris 10 Intel-64
  • MySQL 5.5.x

Lưu ý: DB lớn nhất là DB được sao chép từ máy chủ OLTP DR và ​​DW được tải từ đây. Nó không phải là DW đầy đủ: chỉ 6 tháng đến 6 tuần nên nó nhỏ hơn OLTP DB.

Quan sát trên một máy chủ thử nghiệm

  • 3 kết nối riêng biệt
  • mỗi cái có một đồng thời (và khác nhau) ALTER TABLE...DROP KEY...ADD INDEX
  • 3 bảng có 2,5, 3,8 và 4,5 triệu hàng
  • Việc sử dụng CPU tăng tới 25% (tối đa một lõi) và không cao hơn
  • 3 ALTER mất 12-25 phút (một lần nhỏ nhất mất 4,5)

Câu hỏi

  1. Những cài đặt hoặc bản vá nào được yêu cầu để cho phép nhiều hơn một lõi được sử dụng?
    Đó là, tại sao MySQL không sử dụng tất cả các lõi có sẵn? (giống như các RDBMS khác)
  2. Nó có phải là một hệ quả của việc nhân rộng?

Ghi chú khác

  • Tôi hiểu sự khác biệt giữa "luồng" RDBMS và "luồng" hệ điều hành
  • Tôi không hỏi về bất kỳ hình thức song song nào
  • Một số biến hệ thống cho InnoDB và các luồng là tối ưu phụ
    (tìm kiếm một chiến thắng nhanh chóng)
  • Ngắn hạn, tôi không thể thay đổi cách bố trí đĩa
  • Hệ điều hành có thể được điều chỉnh nếu cần
  • Một ALTER TABLE duy nhất trên bàn nhỏ nhất mất 4,5 phút (gây sốc IMO)

Chỉnh sửa 1

  • innodb_thread_concurrency được đặt thành 8 trên cả hai. Đúng, nó sai nhưng sẽ không khiến MySQL sử dụng nhiều lõi
  • innodb_buffer_pool_size là 80GB trên bản chính, 10GB cho một bài kiểm tra (một trường hợp khác bị tắt). Điều này là ổn cho bây giờ.
  • innodb_file_per_table = BẬT

Chỉnh sửa 2

Để kiểm tra

  • innodb_flush_method không hiển thị dưới dạng O_DIRECT khi cần
  • sẽ theo các cài đặt của RolandoMySQLDBA

Hãy cho tôi biết nếu tôi bỏ lỡ bất cứ điều gì quan trọng

Chúc mừng

Cập nhật

Đã thay đổi cài đặt chủ đề innodb_flush_method + 3 x trong câu trả lời của RolandoMySQLDBA
Kết quả:> 1 lõi được sử dụng cho các bài kiểm tra = kết quả dương tính


@Dtest: innodb_file_per_table = BẬT. SHOW Engine INNODB STATUS \ G chỉ là dòng lệnh?
gbn

@Dtest: Tôi không có đầu ra trong SQLyog và sẽ cần yêu cầu ai đó chạy nó từ dòng lệnh
gbn

1
webyog.com/forums/index.php?showtopic=1290 sẽ hoạt động mà không cần \G. Ngoài ra, tôi nghĩ SHOW INNODB STATUSkhông được ủng hộ SHOW ENGINE INNODB STATUStrong 5.5 (Tôi gặp lỗi khi chạy lệnh cũ.
Derek Downey

1
Mặc dù tất cả các câu trả lời khác đều tốt, vì bạn là nhà phát triển, tôi khuyên bạn nên xem Shard Query code.google.com/p/shard-query Nó có thể giúp bạn, đặc biệt là trong môi trường nhà lưu trữ dữ liệu.
Jonathan

Cảm ơn, đó là một lựa chọn mà chúng tôi đã nghĩ đến. Tôi cũng đang đảm nhận vai trò DBA.
gbn

Câu trả lời:


123

Tôi thực sự đã thảo luận về innodb_thread_concurrency với Chuyên gia MySQL tại hội nghị Percona Live NYC vào tháng 5 năm 2011 .

Tôi đã học được một điều đáng ngạc nhiên: mặc dù tài liệu này, tốt nhất là để innodb_thread_concurrencyở mức 0 (đồng thời vô hạn). Bằng cách đó, InnoDB quyết định số lượng tốt nhất innodb_concurrency_ticketsđể mở cho một thiết lập cá thể MySQL cụ thể.

Khi bạn đặt innodb_thread_concurrencythành 0, bạn có thể đặt innodb_read_io_threadsinnodb_write_io_threads(cả hai kể từ MySQL 5.1,38) thành giá trị tối đa là 64. Điều này sẽ tham gia nhiều lõi hơn.


Sẽ thử cái này. Dù sao tôi cũng sẽ đặt innodb_thread_concurrency thành 0 dựa trên những thứ tôi cũng đã đọc
gbn

9
+1 cho innodb_thread_concurrency = 0
Randomx

3
@gbn - Đến từ anh chàng số 1 trong DBA.SE, một lời cảm ơn là sự củng cố niềm tin và được đánh giá rất cao. Cảm ơn bạn và bạn được chào đón !!!
RolandoMySQLDBA

đặt toàn cầu innodb_read_io_threads = 8 Mã lỗi: 1238. Biến 'innodb_read_io_threads' là biến chỉ đọc
wgq3g23g

2
@ wgq3g23g Nếu bạn đang thực hiện RDS, hãy thay đổi điều đó trong Nhóm tham số DB và khởi động lại thể hiện. Nếu bạn đang làm EC2 hoặc kim loại trần, hãy thêm tùy chọn đó my.cnfvà khởi động lại mysqld. xin vui lòng.
RolandoMySQLDBA

29

MySQL sẽ tự động sử dụng nhiều lõi, do đó, tải 25% của bạn là trùng khớp 1 hoặc cấu hình sai tiềm năng trên Solaris. Tôi sẽ không giả vờ biết cách điều chỉnh solaris, nhưng đây là một bài viết về một số thông tin điều chỉnh dành riêng cho năng lượng mặt trời .

Các trang điều chỉnh InnoDB đã được cung cấp một đại tu trong MySQL 5.5, vì vậy cũng có một số thông tin tốt ở đó. Từ mẹo IO của đĩa InnoDB :

Nếu công cụ hàng đầu Unix hoặc Trình quản lý tác vụ Windows cho thấy tỷ lệ sử dụng CPU với khối lượng công việc của bạn dưới 70%, thì khối lượng công việc của bạn có thể bị giới hạn bởi đĩa. Có thể bạn đang thực hiện quá nhiều cam kết giao dịch hoặc nhóm bộ đệm quá nhỏ. Làm cho vùng đệm lớn hơn có thể giúp ích, nhưng không đặt nó bằng hơn 80% bộ nhớ vật lý.

Một số điều khác để kiểm tra:

  • Chuyển đổi innodb_flush_method thành O_DIRECT là giá trị thử nghiệm. Nếu điều này có ích, bạn có thể cần phải gắn hệ thống tập tin với forcedirectiotùy chọn

  • Thay đổi innodb_flush_log_at_trx_commit từ 1 thành 0 (nếu bạn không mất giây cuối cùng trong sự cố mysql) hoặc 2 (nếu bạn không mất giây cuối cùng trong sự cố hệ điều hành).

  • Kiểm tra giá trị của innodb_use_sys_malloc . Bài viết này có nhiều thông tin hơn về biến.

    Vào thời điểm đó, không có thư viện cấp phát bộ nhớ được điều chỉnh cho CPU đa lõi. Do đó, InnoDB đã triển khai bộ cấp phát bộ nhớ của riêng mình trong hệ thống con mem. Công cụ cấp phát này được bảo vệ bởi một mutex duy nhất, có thể trở thành nút cổ chai.

    Nhưng có một số cảnh báo ở cuối phần về ý nghĩa của việc bật biến (mặc định nó được bật trong 5.5).

    Lưu ý rằng khi cấp phát bộ nhớ InnoDB bị vô hiệu hóa, InnoDB sẽ bỏ qua giá trị của tham số innodb_additable_mem_pool_size.

  • Có thể sự nhân rộng đang gây ra một số vấn đề. Tôi nhận ra rằng bạn không quan tâm đến sự song song, nhưng từ mô tả của worklog này :

    Hiện tại, nhân rộng không có quy mô tốt trên các máy đa lõi. Chuỗi xử lý nô lệ duy nhất thực hiện từng sự kiện sao chép từng cái một và có thể không đối phó với tải được tạo bởi nhiều kết nối máy khách đồng thời được phục vụ bởi CPU của máy chủ chính riêng biệt.

Cuối cùng, InnoDB có thể không phải là công cụ tốt nhất để lưu trữ dữ liệu, vì các hoạt động dựa trên đĩa xảy ra. Bạn có thể xem xét việc thay đổi (các) bảng datwarhouse thành MyISAM được nén .

1 Do trùng hợp, ý tôi là có một nút cổ chai ngăn tải của bạn tăng trên 25%, nhưng không nhất thiết là vấn đề đơn lõi bắt buộc.


Cảm ơn. Phần cài đặt được thêm vào câu hỏi. Vấn đề là một số truy vấn chuyên sâu sử dụng một lõi: chưa cài đặt bộ nhớ hoặc luồng. Nhiều chủ đề vẫn chạy trên cùng một lõi
gbn

@gbn cảm ơn đã cập nhật, vẫn đang tìm kiếm. Tôi đã nghĩ rằng đó là một "sự trùng hợp". Tôi tự hỏi liệu đây có phải là sự cố chỉ dành cho năng lượng mặt trời ( developers.sun.com/solaris/articles/mysql_perf_tune.html ), nhưng không biết nhiều về hệ thống đó.
Derek Downey

1
@Dtest: Tôi sẽ tặc lưỡi bài viết đó cho quản trị viên Solaris Một số nội dung hay ở đó
gbn

1
Bây giờ, sao chép là (tùy chọn) đa luồng trên Slave. InnoDB đã được cải thiện kể từ khi Câu trả lời này được viết. Tôi sẽ không khuyên bạn sử dụng MyISAM, đặc biệt là nếu không nén.
Rick James

15

Một kết nối duy nhất sẽ chỉ sử dụng một lõi đơn. (OK, InnoDB sử dụng các luồng khác, do đó, cho một số xử lý I / O, nhưng điều đó không đáng kể.)

Bạn đã có 3 ALTER, vì vậy bạn không sử dụng nhiều hơn 3 lõi.

Than ôi, thậm chí không THAM GIA sử dụng nhiều lõi.

Cho đến gần đây, nhiều kết nối sẽ đạt tối đa sau 4-8 lõi. Xtradb của Percona (bao gồm trong MariaDB) sử dụng tốt hơn nhiều lõi, nhưng vẫn chỉ có một lõi trên mỗi luồng. Họ đạt tối đa khoảng 32 lõi.


(Cập nhật năm 2015 :) Nhiều kết nối với 5,6 tối đa ở khoảng 48 lõi. 5.7 hứa hẹn sẽ còn tốt hơn nữa. (Vì vậy, điểm chuẩn của Oracle nói.) Nhưng vẫn không sử dụng nhiều lõi cho một kết nối.
Rick James

Cập nhật (sau khi đến OpenWorld của Oracle): phiên bản mới 8.x sẽ không có bất kỳ sự song song nào.
Rick James

9

IMHO và trong trường hợp sử dụng được mô tả, bạn sẽ không bao giờ sử dụng nhiều hơn một lõi. Lý do là khối lượng công việc của bạn bị ràng buộc IO, không bị ràng buộc CPU. Vì 3 kết nối của bạn đang tạo một Chỉ mục mới, mỗi trong số chúng cần đọc toàn bộ bảng từ đĩa: đây là những gì đang làm mất thời gian, không tính toán các Chỉ mục.


8

Hãy xem xét rằng nút cổ chai của bạn có thể là hiệu suất IO của hệ thống tệp của bạn.

Ngoài các cài đặt được đề xuất bởi @RolandoMySQLDBA , tôi cũng đặt noatimecài đặt gắn kết /etc/fstabcho phân vùng chứa thư mục dữ liệu mysql của tôi ( /data01/mysqltrong trường hợp của tôi, /dev/sdb1được gắn vào /data01).

Theo mặc định, linux ghi lại thời gian truy cập cho MỌI đĩa đọc hoặc ghi, điều này ảnh hưởng tiêu cực đến hiệu suất IO, đặc biệt đối với các ứng dụng IO cao như cơ sở dữ liệu. Điều này có nghĩa là ngay cả việc đọc dữ liệu từ một tệp cũng kích hoạt ghi vào đĩa ... WAT!

Để tắt tính năng này, hãy thêm noatimetùy chọn gắn kết /etc/fstabcho điểm gắn kết mong muốn như sau (ví dụ trong trường hợp của tôi):

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

Sau đó, phân vùng lại:

mount -o,remount /data01

Điều này sẽ tăng hiệu suất đọc / ghi của các ứng dụng sử dụng phân vùng đó. NHƯNG ... không có gì nhịp đập giữ tất cả dữ liệu của bạn trong bộ nhớ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.