nodejs mysql Lỗi: Mất kết nối Máy chủ đóng kết nối


89

khi tôi sử dụng nút mysql, một lỗi xuất hiện trong khoảng từ 12:00 đến 2:00 rằng kết nối TCP bị máy chủ tắt. Đây là toàn bộ tin nhắn:

Error: Connection lost: The server closed the connection.
at Protocol.end (/opt/node-v0.10.20-linux-x64/IM/node_modules/mysql/lib/protocol/Protocol.js:73:13)
at Socket.onend (stream.js:79:10)
at Socket.EventEmitter.emit (events.js:117:20)
at _stream_readable.js:920:16
at process._tickCallback (node.js:415:13)

giải pháp . Tuy nhiên, sau khi tôi thử bằng cách này, vấn đề cũng xuất hiện. bây giờ tôi không biết làm thế nào để làm. Có ai gặp vấn đề này không?

Đây là cách tôi đã viết theo giải pháp:

    var handleKFDisconnect = function() {
    kfdb.on('error', function(err) {
        if (!err.fatal) {
            return;
        }
        if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
            console.log("PROTOCOL_CONNECTION_LOST");
            throw err;
        }
        log.error("The database is error:" + err.stack);

        kfdb = mysql.createConnection(kf_config);

        console.log("kfid");

        console.log(kfdb);
        handleKFDisconnect();
    });
   };
   handleKFDisconnect();

Câu trả lời:


160

Cố gắng sử dụng mã này để xử lý ngắt kết nối máy chủ:

var db_config = {
  host: 'localhost',
    user: 'root',
    password: '',
    database: 'example'
};

var connection;

function handleDisconnect() {
  connection = mysql.createConnection(db_config); // Recreate the connection, since
                                                  // the old one cannot be reused.

  connection.connect(function(err) {              // The server is either down
    if(err) {                                     // or restarting (takes a while sometimes).
      console.log('error when connecting to db:', err);
      setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
    }                                     // to avoid a hot loop, and to allow our node script to
  });                                     // process asynchronous requests in the meantime.
                                          // If you're also serving http, display a 503 error.
  connection.on('error', function(err) {
    console.log('db error', err);
    if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
      handleDisconnect();                         // lost due to either server restart, or a
    } else {                                      // connnection idle timeout (the wait_timeout
      throw err;                                  // server variable configures this)
    }
  });
}

handleDisconnect();

Trong mã của bạn, tôi thiếu các phần sau connection = mysql.createConnection(db_config);


ok, tôi sẽ thử cái này. nhưng làm thế nào tôi có thể mô phỏng siutation này
jackieLin

1
Chỉ là một mẹo: Tôi đang thử nghiệm kết nối lại bằng cách khởi động lại dịch vụ mysql để đảm bảo mọi thứ hoạt động tốt.
kriskodzi

2
@jackieLin, bạn có thể mô phỏng tình huống, khởi động lại dịch vụ mysql, trên dịch vụ sudo ubuntu khởi động lại mysql
igor

1
Cảm ơn bạn @ user3073745, sự cố này được giải quyết bằng cách khởi động lại
jackieLin

1
Hoạt động hoàn hảo cho nút 8. *, npm 5.6.0 và mysql: 5.7 ... Cảm ơn !!
JRichardsz

47

Tôi không nhớ lại trường hợp sử dụng ban đầu của mình cho cơ chế này. Ngày nay, tôi không thể nghĩ ra bất kỳ trường hợp sử dụng hợp lệ nào.

Máy khách của bạn sẽ có thể phát hiện khi kết nối bị mất và cho phép bạn tạo lại kết nối. Nếu điều quan trọng là một phần của logic chương trình được thực thi bằng cách sử dụng cùng một kết nối, thì hãy sử dụng các giao dịch.

tl; dr; Không sử dụng phương pháp này.


Một giải pháp thực dụng là buộc MySQL giữ kết nối tồn tại:

setInterval(function () {
    db.query('SELECT 1');
}, 5000);

Tôi thích giải pháp này cho nhóm kết nối và xử lý ngắt kết nối vì nó không yêu cầu cấu trúc mã của bạn theo cách nhận biết được sự hiện diện của kết nối. Thực hiện một truy vấn cứ sau 5 giây đảm bảo rằng kết nối sẽ vẫn tồn tại và PROTOCOL_CONNECTION_LOSTkhông xảy ra.

Hơn nữa, phương pháp này đảm bảo rằng bạn đang giữ cho cùng một kết nối tồn tại , trái ngược với việc kết nối lại. Cái này quan trọng. Hãy xem xét điều gì sẽ xảy ra nếu tập lệnh của bạn dựa vào LAST_INSERT_ID()và kết nối mysql đã được đặt lại mà bạn không biết về nó?

Tuy nhiên, điều này chỉ đảm bảo rằng thời gian chờ kết nối ( wait_timeoutinteractive_timeout) không xảy ra. Nó sẽ thất bại, như mong đợi, trong tất cả các tình huống khác. Do đó, hãy đảm bảo xử lý các lỗi khác.


1
Chỉ tò mò, bạn sẽ đặt truy vấn db đó ở đâu? Ở cuối máy chủ nodejs phải không? Vấn đề duy nhất là, tôi chỉ sử dụng mysql để xác thực người dùng một lần và sau đó tôi lưu trữ dữ liệu của họ trong một đối tượng người dùng tạm thời cho trò chơi rpg của tôi. Tôi không biết tại sao hôm nay tôi lại gặp lỗi đóng mysql này một cách ngẫu nhiên, hmm. Tôi cũng đang đóng kết nối đúng cách, v.v.
NiCk Newman

1
Bạn nên kết nối với cơ sở dữ liệu và ngắt kết nối theo yêu cầu. Giải pháp này dành cho các dịch vụ chạy liên tục và sử dụng kết nối cơ sở dữ liệu mọi lúc.
Gajus

1
Không có âm thanh nào có thể xảy ra vì mã của bạn tuân theo mẫu được mô tả (tương tự như gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Nếu điều này chỉ xảy ra một hoặc hai lần trong số hàng nghìn truy vấn, tôi sẽ cho rằng các vấn đề kết nối, quá tải máy chủ hoặc một số vấn đề dọc theo những dòng đó.
Gajus

2
Đó có thể là gợi ý tồi tệ nhất từng có! Một người gợi ý rằng bạn nên đóng cơ sở dữ liệu bằng các truy vấn để kết nối sẽ không hoạt động? Điều gì xảy ra nếu 100 người làm điều này? hoặc tại sao không phải là 10 000, Nếu ứng dụng của bạn không ghi nhận, chuỗi sẽ được trả về Nhóm luồng MYSQL KHÔNG lưu trữ một chuỗi để mã yếu của bạn không bị hỏng !, trong trường hợp này, bạn triển khai chức năng để kết nối lại nếu sự kiện đó xảy ra ! Thật là không thể tin được, thật là tuyệt vời, cảm ơn chúa vì FB đã không có bạn là kiến ​​trúc sư chính !!
Patrik Forsberg

2
Tôi đã cập nhật câu trả lời để phản ánh rằng tôi không khuyến nghị cách tiếp cận này. Cảm ơn vì Patrik.
Gajus



1

Việc tạo và hủy các kết nối trong mỗi truy vấn có thể phức tạp, tôi đã phải đau đầu với việc di chuyển máy chủ khi quyết định cài đặt MariaDB thay vì MySQL. Vì lý do nào đó trong tệp etc / my.cnf, tham số wait_timeout có giá trị mặc định là 10 giây (nguyên nhân là không thể triển khai tính năng duy trì). Sau đó, giải pháp được đặt là 28800, tức là 8 giờ. Chà, tôi hy vọng có thể giúp ai đó với "güevonada" này ... thứ lỗi cho tôi vì tiếng Anh của tôi không tốt.

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.