Các --single-transaction
tùy chọn mysqldump
không làm một FLUSH TABLES WITH READ LOCK
trước khi bắt đầu công việc sao lưu nhưng chỉ trong điều kiện nhất định. Một trong những điều kiện đó là khi bạn cũng chỉ định --master-data
tùy chọn.
Trong mã nguồn, từ mysql-5.6.19/client/mysqldump.c
dòng 5797:
if ((opt_lock_all_tables || opt_master_data ||
(opt_single_transaction && flush_logs)) &&
do_flush_tables_read_lock(mysql))
goto err;
Để có được khóa chắc chắn trên tọa độ binlog chính xác trước khi bắt đầu giao dịch đọc lặp lại, --master-data
tùy chọn kích hoạt khóa này để có được và sau đó được giải phóng sau khi đã đạt được tọa độ binlog.
Trong thực tế, mysqldump
việc FLUSH TABLES
tiếp theo là bởi FLUSH TABLES WITH READ LOCK
vì thực hiện cả hai điều này cho phép khóa đọc được nhanh hơn trong trường hợp việc xả ban đầu mất một thời gian.
...Tuy nhiên...
Ngay sau khi nó có được tọa độ binlog, sẽ mysqldump
đưa ra một UNLOCK TABLES
câu lệnh, do đó, không nên có bất cứ điều gì chặn do kết quả của việc bạn bắt đầu. Không có bất kỳ chủ đề nào Waiting for table flush
là kết quả của giao dịch mysqldump
đang giữ.
Khi bạn nhìn thấy một sợi trong Waiting for table flush
nhà nước, mà nên có nghĩa là FLUSH TABLES [WITH READ LOCK]
tuyên bố được đưa ra và vẫn chạy khi truy vấn bắt đầu - vì vậy truy vấn phải đợi cho tuôn ra bảng, trước khi nó có thể thực thi. Trong trường hợp danh sách quy trình bạn đã đăng, mysqldump
đang đọc từ cùng bảng này và truy vấn đã chạy được một lúc, nhưng các truy vấn chặn đã không bị chặn trong suốt thời gian dài.
Tất cả điều này cho thấy rằng một cái gì đó khác đã xảy ra.
Có một vấn đề tồn tại lâu dài được giải thích trong Bug # 44884 với cách thức FLUSH TABLES
hoạt động trong nội bộ. Tôi sẽ không ngạc nhiên nếu vấn đề vẫn còn, tôi sẽ ngạc nhiên nếu vấn đề này đã được "khắc phục" bởi vì đây là một vấn đề rất phức tạp để giải quyết - hầu như không thể thực sự khắc phục trong môi trường đồng thời cao - và mọi nỗ lực tại sửa chữa nó mang một rủi ro đáng kể trong việc phá vỡ một cái gì đó khác, hoặc tạo ra hành vi mới, khác biệt và vẫn không mong muốn.
Có vẻ như đây sẽ là lời giải thích cho những gì bạn đang thấy.
Đặc biệt:
nếu bạn có một truy vấn chạy dài chạy trên một bảng và phát hành FLUSH TABLES
, thì FLUSH TABLES
sẽ chặn cho đến khi truy vấn chạy dài hoàn thành.
ngoài ra, bất kỳ truy vấn nào bắt đầu sau khi FLUSH TABLES
được đưa ra sẽ chặn cho đến khi FLUSH TABLES
hoàn thành.
ngoài ra, nếu bạn giết FLUSH TABLES
truy vấn, các truy vấn đang chặn sẽ vẫn chặn truy vấn chạy dài ban đầu, truy vấn đang chặn FLUSH TABLES
truy vấn, bởi vì mặc dù FLUSH TABLES
truy vấn bị giết không kết thúc, bảng đó (hoặc hơn nữa, liên quan đến truy vấn chạy dài) vẫn đang trong quá trình xóa và việc xử lý đang chờ xử lý sẽ xảy ra ngay khi truy vấn chạy dài kết thúc - nhưng không phải trước đó.
Kết luận có khả năng ở đây là một quy trình khác - có thể là một mysqldump khác, hoặc một truy vấn không chính xác, hoặc một quy trình giám sát kém bằng văn bản đã cố gắng xóa một bảng.
Truy vấn đó sau đó đã bị giết hoặc hết thời gian bởi một cơ chế không xác định, nhưng hậu quả của nó đã kéo dài cho đến khi mysqldump
đọc xong từ bảng trong câu hỏi.
Bạn có thể sao chép điều kiện này bằng cách thử FLUSH TABLES
trong khi một truy vấn chạy dài đang được xử lý. Sau đó bắt đầu một truy vấn khác, sẽ chặn. Sau đó, giết FLUSH TABLES
truy vấn, sẽ không bỏ chặn truy vấn mới nhất. Sau đó, giết truy vấn đầu tiên hoặc để nó kết thúc và truy vấn cuối cùng sẽ chạy thành công.
Như một suy nghĩ lại, điều này không liên quan:
Trx read view will not see trx with id >= 1252538405, sees < 1252538391
Điều đó là bình thường, bởi vì mysqldump --single-transaction
các vấn đề a START TRANSACTION WITH CONSISTENT SNAPSHOT
, ngăn không cho dữ liệu bị hủy dữ liệu đã bị thay đổi trong khi bãi chứa đang diễn ra. Nếu không có điều đó, tọa độ binlog thu được khi bắt đầu sẽ là vô nghĩa, vì --single-transaction
nó sẽ không phải là những gì nó tuyên bố là. Điều này không nên liên quan đến Waiting for table flush
vấn đề này, vì giao dịch này rõ ràng không có khóa.