Bạn có gặp phải tình trạng khởi động MySQL chậm ở chế độ GTID không? Gần đây, chúng tôi đã gặp phải sự cố này trên một trong những triển khai lưu trữ MySQL của mình và đã đặt ra cách giải quyết vấn đề. Trong blog này, chúng tôi phân tích vấn đề có thể làm chậm thời gian khởi động lại MySQL của bạn, cách gỡ lỗi cho quá trình triển khai của bạn và những gì bạn có thể làm để giảm thời gian bắt đầu và nâng cao hiểu biết của bạn về sao chép dựa trên GTID.
Cách chúng tôi phát hiện ra vấn đề
Chúng tôi đang điều tra thời gian khởi động MySQL chậm trên triển khai MySQL 5.7.21 cấp thấp, dựa trên đĩa đã bật chế độ GTID. Hệ thống là một phần của cặp master-slave và chịu tải trọng ghi vừa phải. Khi khởi động lại trong thời gian bảo trì theo lịch trình, chúng tôi nhận thấy rằng máy chủ cơ sở dữ liệu mất 5-10 phút để khởi động và bắt đầu chấp nhận kết nối. Sự chậm trễ như vậy không có ý nghĩa gì, vì vậy chúng tôi bắt đầu điều tra.
Gỡ lỗi Thời gian bắt đầu MySQL chậm của bạn
Chúng tôi đã sử dụng công cụ Percona phổ biến pt-ioprofile để xem cơ sở dữ liệu đang hoạt động như thế nào. pt-ioprofile là một tiện ích rất quan trọng trong bộ công cụ phổ biến của Percona được sử dụng để gỡ lỗi các sự cố MySQL và bạn có thể xem danh sách đầy đủ các tính năng trong tài liệu của chúng. pt-ioprofile công cụ sử dụng strace và lsof để xem I / O của một quy trình và in ra một bảng các tệp và hoạt động I / O.
Vì vậy, chúng tôi đã khởi động MySQL, đợi mysqld quy trình để tạo và bắt đầu pt-ioprofile để xem vấn đề có thể là gì:
# pt-ioprofile --profile-process mysqld --run-time 200 Tue Oct 9 15:42:24 UTC 2018 Tracing process ID 18677 total pread read pwrite write fsync fdatasync open close getdents lseek fcntl filename ... 216.550641 0.000000 216.550565 0.000000 0.000000 0.000000 0.000000 0.000015 0.000040 0.000000 0.000021 0.000000 /mysql_data/binlogs/mysql-bin.000014 ...
Khởi động lại MySQL của bạn làm chậm điều gì?
Khi chạy phần mềm này nhiều lần, chúng tôi đã quan sát thấy những điều sau:
- mysqld quy trình đã dành phần lớn thời gian để đọc tệp nhật ký nhị phân mới nhất. Đây là trường hợp ngay cả khi máy chủ đã được dừng một cách duyên dáng và không cần khôi phục sự cố, v.v.
- Máy chủ cũng đã dành một lượng thời gian đáng kể để tải tệp dữ liệu InnoDB, nhưng thời gian đó nhỏ hơn nhiều so với thời gian dành cho việc đọc tệp nhật ký nhị phân mới nhất.
- Nếu máy chủ được khởi động lại ngay lập tức, quá trình khởi động lại sau đó sẽ nhanh hơn nhiều.
- Vì việc tắt cơ sở dữ liệu sẽ xóa nhật ký nhị phân và tạo một nhật ký mới khi khởi động, chúng tôi đã thực hiện một thử nghiệm bổ sung - trước khi tắt máy chủ, chúng tôi đã xóa nhật ký nhị phân. Máy chủ sau đó khởi động lại rất nhanh.
Những quan sát này rõ ràng chỉ ra rằng MySQL đã dành nhiều thời gian để đọc tệp nhật ký nhị phân mới nhất. Nếu tệp nhỏ, giống như khi tệp nhật ký được xóa trước khi tắt máy, thì quá trình khởi động rất nhanh.
Thời gian bắt đầu MySQL chậm trong GTID? Kích thước tệp nhật ký nhị phân của bạn có thể là vấn đềNhấp vào Tweet
Hiểu khôi phục GTID trong Binlog
Hóa ra, để điền các giá trị của gtid_executed và gtid_purged, máy chủ MySQL phải phân tích cú pháp các tệp nhật ký nhị phân.
Dưới đây là tóm tắt về đề xuất phương pháp tài liệu MySQL 5.7 dựa trên cách đọc SAI hoặc ĐÚNG:
Khi binlog_gtid_simple_recovery =SAI:
Để tính toán gtid_executed:
- Lặp lại các tệp nhật ký nhị phân từ tệp nhật ký mới nhất, dừng lại ở tệp đầu tiên có Previous_gtids_log_event mục nhập.
- Sử dụng tất cả GTID từ Previous_gtids_log_event và Gtid_log_events từ tệp nhật ký nhị phân này và lưu trữ bộ GTID này trong nội bộ. Nó được gọi là gtids_in_binlog.
- Giá trị của gtid_executed được tính là hợp nhất của gtids_in_binlog và GTID trong bảng mysql.gtid_executed .
Quá trình này có thể rất tốn thời gian nếu có một số lượng lớn tệp nhật ký nhị phân không có GTID, chẳng hạn như được tạo khi gtid_mode =TẮT.
Tương tự, để tính gtid_purged:
- Lặp lại các tệp nhật ký nhị phân từ tệp cũ nhất đến mới nhất, dừng lại ở nhật ký nhị phân đầu tiên chứa tệp không có gì Trước_gtids_log_event (có ít nhất một GTID) hoặc có ít nhất một Gtid_log_event .
- Đọc Previous_gtids_log_event từ tệp này. Tính toán biến nội bộ gtids_in_binlog_not_purged vì bộ GTID này được trừ khỏi gtids_in_binlog.
- Giá trị của gtid_purged được đặt thành gtid_executed , trừ gtids_in_binlog_not_purged .
Vì vậy, điều này tạo cơ sở cho sự hiểu biết của chúng tôi về cách mọi thứ được sử dụng để hoạt động trong các phiên bản cũ hơn. Tuy nhiên, có thể thực hiện một số tối ưu hóa nhất định khi binlog_gtid_simple_recovery là đúng. Đây là trường hợp chúng tôi quan tâm:
Khi binlog_gtid_simple_recovery =ĐÚNG:
(Lưu ý, đây là giá trị mặc định trong MySQL 5.7.7 trở lên)
- Chỉ đọc các tệp nhật ký nhị phân cũ nhất và mới nhất.
- Tính toán gtid_purged từ Previous_gtids_log_event hoặc Gtid_log_event được tìm thấy trong tệp nhật ký nhị phân cũ nhất.
- Tính toán gtid_executed từ Previous_gtids_log_event hoặc Gtid_log_event được tìm thấy trong tệp nhật ký nhị phân mới nhất.
- Do đó, chỉ có hai tệp nhật ký nhị phân được đọc trong khi khởi động lại máy chủ hoặc khi xóa nhật ký nhị phân.
Vì vậy, đối với MySQL phiên bản 5.7.7 trở lên, tệp nhật ký nhị phân mới nhất và cũ luôn được đọc trong khi khởi động hệ thống để khởi tạo chính xác các biến hệ thống GTID. Việc đọc tệp nhật ký nhị phân cũ nhất không quá đắt vì sự kiện mà MySQL đang tìm kiếm, Previous_gtids_log_event, luôn là sự kiện đầu tiên trong tệp nhật ký nhị phân.
Tuy nhiên, để tính toán chính xác gtid_executed , máy chủ phải đọc qua toàn bộ tệp nhật ký nhị phân mới nhất và thu thập tất cả các sự kiện trong tệp đó. Vì vậy, thời gian khởi động hệ thống trở nên tỷ lệ thuận với kích thước của tệp nhật ký nhị phân mới nhất .
Lưu ý rằng tình hình thậm chí còn tồi tệ hơn khi binlog_gtid_simple_recovery là FALSE . Vì nó không còn là tùy chọn mặc định trong các bản phát hành gần đây, nó không còn là vấn đề đáng lo ngại.
Cách giải quyết thời gian bắt đầu chậm của bạn
Sau khi hiểu nguyên nhân của sự cố mà chúng tôi gặp phải, giải pháp mà chúng tôi quyết định khá rõ ràng - giảm kích thước của các tệp nhật ký nhị phân. Kích thước mặc định của tệp nhật ký nhị phân là 1GB. Cần có thời gian để phân tích cú pháp thông qua một tệp có kích thước này trong khi khởi động, do đó, việc giảm giá trị của max_binlog_size là hợp lý xuống một giá trị thấp hơn.
Nếu giảm kích thước của tệp nhật ký nhị phân không phải là một tùy chọn, thì việc xóa tệp nhật ký nhị phân ngay trước khi quá trình mysqld ngừng bảo trì có thể giúp để giảm thời gian khôi phục GTID của binlog.