2011-11-24 38 views
5

Xin chào Tôi đang gặp sự cố trên máy chủ của tôi vào phút này vì một số truy vấn MySQL đang mất nhiều thời gian để chạy và hogging tài nguyên trên máy chủ.Dù sao để hạn chế truy vấn MySQL Thời gian thực hiện?

Tôi đang trong quá trình tối ưu hóa tất cả các truy vấn để cải thiện hiệu suất, nhưng khi chúng tôi sử dụng số lượng hợp lý các ứng dụng của bên thứ ba trên máy chủ bằng mysql, tôi hy vọng sẽ đưa ra một biện pháp bảo vệ để ngăn chặn các vấn đề trong tương lai .

Những gì tôi cần là thứ tôi có thể áp dụng cho tất cả các truy vấn nhưng có khả năng ghi đè lên cơ sở truy vấn cho một số báo cáo phức tạp hơn.

Tôi đã dành thời gian googling để tìm một giải pháp nhưng cho đến nay không có may mắn,

Nhờ sự giúp đỡ của bạn

+1

thiết lập quy trình daemon, đó là bỏ phiếu mỗi X giây 'show PROCESSLIST' từ MySQL và giết chết tất cả các truy vấn tham gia hơn Y giây – rabudde

+0

vâng tôi thấy cách tiếp cận tương tự như sau sử dụng PHP mà được tất cả các tiến trình đang chạy và thực hiện lần và sau đó bạn có thể giết chúng bằng lệnh mysql. Một ý tưởng thông minh, rất đáng ngạc nhiên không phải là một cái gì đó tự nhiên bảo vệ chống lại điều này. Có vẻ lạ rằng mysql sẽ cho phép các tiến trình cơ bản chạy mãi mãi và hog tất cả các tài nguyên hệ thống trong tiến trình. – x9sim9

+0

Lớp cơ sở DbCommand trong .NET có thuộc tính CommandTimeout đặt thời gian chờ trước khi chấm dứt nỗ lực thực thi lệnh và tạo ra lỗi. – Devart

Trả lời

0

Không có cách nào để làm điều đó bằng các tùy chọn MySQL. Nhưng bạn vẫn có thể làm điều đó bằng cách sử dụng quy trình daemon như @rabudde khuyên.

Trong trường hợp này, nếu bạn hủy quá trình, bạn sẽ hủy giao dịch và nó sẽ được khôi phục.

+1

Xin lưu ý rằng các giao dịch quay lại cũng có thể đặt một tải đáng kể trên máy chủ! Thật không may điều này khó có thể được dự đoán, nhưng như một quy tắc của ngón tay cái bạn nên biết rằng nếu một giao dịch đã được chạy trong một thời gian và sẽ liên lạc nhiều hồ sơ, thời gian rollback của nó sẽ tăng lên. Điều này thậm chí còn tồi tệ hơn khi có một số giao dịch tương tác (bao gồm SELECTING) với các hàng tương tự. –

+0

May mắn thay tôi có thể nhận được các truy vấn đang được thực hiện như vậy sẽ đặt một cái gì đó tại chỗ để cho phép truy vấn không SELECT phòng thở nhiều hơn. TBH cho đến nay không có vấn đề với hiệu năng liên quan đến INSERT/UPDATE/REPLACE cho đến nay đã được SELECT truy vấn thường với mysql chọn các chỉ mục không chính xác, và đáng ngạc nhiên FORCE INDEX (chính) sửa khoảng 90% các truy vấn này! – x9sim9

3

Đây là giải pháp hoàn toàn php có vẻ là giải pháp đơn giản nhất từ ​​những gì tôi đã quản lý để tìm kiếm cho đến thời điểm này.

$result = mysql_query("SHOW FULL PROCESSLIST"); 
while ($row=mysql_fetch_array($result)) 
{ 
    $process_id = $row["Id"]; 
    if ($row["Time"] > 200) 
    { 
    $sql="KILL {$process_id}"; 
    mysql_query($sql); 
    } 
} 

Và chạy từ tập lệnh CRON sau mỗi 60 giây.

Nếu ai không tìm thấy một giải pháp tốt hơn cho vấn đề này xin vui lòng cho tôi biết

3

bạn có thể sử dụng quy trình sau để kiểm tra các truy vấn chạy quá 300 giây. sự kiện chạy thủ tục định kỳ và giết tất cả các truy vấn chạy dài.

CREATE PROCEDURE DBNAME.kill_long_running_queries() 
BEGIN 

    DECLARE v_qid BIGINT; 
    DECLARE v_finished INT DEFAULT 0; 
    DECLARE c_queries CURSOR FOR SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE COMMAND = 'Query' AND TIME > 300; 
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_finished = 1; 

    OPEN c_queries; 

    l_fetch_queries: LOOP 
    FETCH c_queries INTO v_qid; 
    IF v_qid > 0 THEN 
     KILL QUERY v_qid; 
    END IF; 
    IF v_finished THEN 
     LEAVE l_fetch_queries; 
    END IF; 
    END LOOP l_fetch_queries; 
    CLOSE c_queries; 

END 

CREATE EVENT kill_long_running_queries 
ON SCHEDULE EVERY 60 SECOND 
DO CALL DBNAME.kill_long_running_queries(); 
+0

Điều này hoạt động tuyệt vời, cảm ơn bạn! Chưa bao giờ nghe về các sự kiện MySQL trước đây, cần thêm dòng 'event_scheduler = 1' vào _my.cnf_ để kích hoạt chúng. –

Các vấn đề liên quan