nodejs mysql Kesalahan: Koneksi terputus Server menutup koneksi

93

ketika saya menggunakan node mysql, kesalahan muncul antara 12: 00-2: 00 bahwa koneksi TCP dimatikan oleh server. Ini adalah pesan lengkapnya:

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)

Ada solusinya . Namun setelah saya coba dengan cara ini, masalah juga muncul. sekarang saya tidak tahu bagaimana melakukannya. Apakah ada yang menemui masalah ini?

Berikut adalah cara saya menulis ikuti solusinya:

    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();
jackieLin
sumber
Perhatikan bahwa dalam kode Anda Anda memiliki pesan yang salah: if (err.code !== 'PROTOCOL_CONNECTION_LOST') { console.log("PROTOCOL_CONNECTION_LOST"); throw err; }. Anda menjalankan if()blok jika tidak PROTOCOL_CONNECTION_LOST , namun pesan mengatakan itu adalah kesalahan itu ... mungkin sangat membingungkan.
Alexis Wilke

Jawaban:

164

Coba gunakan kode ini untuk menangani pemutusan server:

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();

Dalam kode Anda, saya kehilangan bagian setelahnya connection = mysql.createConnection(db_config);

CloudyMarble
sumber
ok, saya akan coba ini. tetapi bagaimana saya bisa mensimulasikan siutasi ini
jackieLin
1
Hanya tip: Saya menguji menghubungkan kembali dengan memulai kembali layanan mysql untuk memastikan semuanya berfungsi dengan baik.
kriskodzi
2
@jackieLin Anda dapat mensimulasikan situasi, memulai ulang layanan mysql, pada layanan ubuntu sudo mysql restart
igor
1
Terima kasih @ user3073745, masalah ini diselesaikan dengan restart
jackieLin
1
Bekerja dengan sempurna untuk node 8. *, npm 5.6.0 dan mysql: 5.7 ... Terima kasih !!
JRichardsz
47

Saya tidak ingat kasus penggunaan asli saya untuk mekanisme ini. Saat ini, saya tidak dapat memikirkan kasus penggunaan yang valid.

Klien Anda harus dapat mendeteksi saat koneksi terputus dan memungkinkan Anda membuat ulang koneksi. Jika penting bahwa bagian dari logika program dieksekusi menggunakan koneksi yang sama, maka gunakan transaksi.

tl; dr; Jangan gunakan metode ini.


Solusi pragmatis adalah memaksa MySQL untuk menjaga koneksi tetap hidup:

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

Saya lebih suka solusi ini daripada kumpulan koneksi dan menangani pemutusan koneksi karena tidak perlu menyusun kode Anda dengan cara yang menyadari kehadiran koneksi. Membuat kueri setiap 5 detik memastikan bahwa koneksi akan tetap hidup danPROTOCOL_CONNECTION_LOST tidak terjadi.

Selanjutnya, metode ini memastikan bahwa Anda menjaga koneksi yang sama tetap hidup , bukan menghubungkan kembali. Ini penting. Pertimbangkan apa yang akan terjadi jika skrip Anda mengandalkan LAST_INSERT_ID()dan koneksi mysql telah disetel ulang tanpa Anda menyadarinya?

Namun, ini hanya memastikan bahwa waktu koneksi habis ( wait_timeoutdan interactive_timeout) tidak terjadi. Ini akan gagal, seperti yang diharapkan, di semua skenario lainnya. Oleh karena itu, pastikan untuk menangani kesalahan lainnya.

Gajus
sumber
1
Hanya ingin tahu, di mana Anda akan meletakkan kueri db itu? Di bagian bawah server nodejs kan? Satu-satunya masalah adalah, saya hanya menggunakan mysql untuk mengotentikasi pengguna satu kali, dan kemudian saya menyimpan data mereka di objek pengguna sementara untuk game rpg saya. Saya tidak tahu mengapa saya mendapatkan kesalahan ditutup mysql ini secara acak hari ini, hmm. Saya menutup koneksi dengan benar, dll juga.
NiCk Newman
1
Anda harus terhubung ke database dan memutuskan koneksi berdasarkan permintaan. Solusi ini untuk layanan yang berjalan terus menerus dan memanfaatkan koneksi database setiap saat.
Gajus
1
Kedengarannya tidak mungkin karena kode Anda mengikuti pola yang dijelaskan (mirip dengan gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Jika ini terjadi hanya sekali atau dua kali dari ribuan kueri, saya akan menganggap masalah konektivitas, server kelebihan beban, atau sesuatu di sepanjang garis itu.
Gajus
3
Itu mungkin saran terburuk yang pernah ada! Seseorang menyarankan bahwa Anda harus memalu database dengan kueri hanya agar koneksi tidak berjalan? Apa yang terjadi jika 100 orang melakukan ini? atau mengapa tidak 10.000, Jika aplikasi Anda tidak mencatat, utas harus dikembalikan ke MYSQL Thread Pool TIDAK memonopoli utas sehingga kode lemah Anda tidak rusak !, dalam hal ini Anda menerapkan fungsionalitas untuk menyambungkan kembali jika peristiwa seperti itu telah terjadi ! Ini luar biasa, sungguh sungguh terima kasih Tuhan bahwa FB tidak menjadikan Anda sebagai arsitek utama !!
Patrik Forsberg
2
Saya telah memperbarui jawaban untuk mencerminkan bahwa saya tidak merekomendasikan pendekatan ini. Terima kasih atas perhatiannya, Patrik.
Gajus
4

solusi yang lebih baik adalah dengan menggunakan pool - sakit menangani ini untuk Anda.

const pool = mysql.createPool({
  host: 'localhost',
  user: '--',
  database: '---',
  password: '----'
});

// ... later
pool.query('select 1 + 1', (err, rows) => { /* */ });

https://github.com/sidorares/node-mysql2/issues/836

Lalgulab Khatkar
sumber
Ini harus menjadi jawaban yang diterima. Menggunakan mekanisme pool akan menyembunyikan semua detail rumit tentang bagaimana menangani waktu koneksi habis. Juga, ada dokumentasi tentang cara menggunakannya di node_modules/mysql/Readme.mdfile yang disertakan dengan modul node MySQL.
Alexis Wilke
1

Membuat dan menghancurkan koneksi di setiap kueri mungkin rumit, saya mengalami sakit kepala dengan migrasi server ketika saya memutuskan untuk menginstal MariaDB, bukan MySQL. Untuk beberapa alasan di file etc / my.cnf parameter wait_timeout memiliki nilai default 10 detik (ini menyebabkan persistensi tidak dapat diimplementasikan). Kemudian, solusinya ditetapkan pada 28800, yaitu 8 jam. Yah, saya harap membantu seseorang dengan "güevonada" ini ... maafkan bahasa Inggris saya yang buruk.

Menara Aleks
sumber