nodejs mysql Помилка: підключення втрачено Сервер перервав з’єднання


89

коли я використовую вузол mysql, з 12:00 до 2:00 з'являється помилка, що TCP-з'єднання відключається сервером. Ось повне повідомлення:

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)

Існує рішення . Однак після того, як я спробую цим способом, проблема також з'являється. тепер я не знаю, як це зробити. Хтось стикається з цією проблемою?

Ось спосіб, як я писав, дотримуйтесь рішення:

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

Відповіді:


161

Спробуйте використати цей код для обробки відключення сервера:

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

У вашому коді мені не вистачає частин після connection = mysql.createConnection(db_config);


добре, я спробую це. але як я міг змоделювати цю ситуацію
jackieLin

1
Тільки порада: я тестую повторне підключення, перезапустивши службу mysql, щоб переконатися, що все працює добре.
kriskodzi

2
@jackieLin ти можеш змоделювати ситуацію, перезапустивши службу mysql, на службі ubuntu sudo mysql restart
igor

1
Дякую @ user3073745, ця проблема вирішена перезапуском
jackieLin

1
Відмінно працює для вузла 8. *, npm 5.6.0 та mysql: 5.7 ... Дякую !!
JRichardsz

47

Я не згадую свого оригінального варіанту використання цього механізму. На сьогоднішній день я не можу придумати жодного дійсного випадку використання.

Ваш клієнт повинен мати можливість виявити втрату зв’язку та дозволити вам заново створити зв’язок. Якщо важливо, щоб частина логіки програми виконувалась за допомогою того самого підключення, тоді використовуйте транзакції.

tl; dr; Не використовуйте цей метод.


Прагматичне рішення - змусити MySQL підтримувати зв’язок:

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

Я віддаю перевагу цьому рішенню пулу з'єднань та обробці роз'єднання, оскільки воно не вимагає структурувати ваш код таким чином, щоб усвідомлювати наявність з'єднання. Роблячи запит кожні 5 секунд, гарантує, що зв’язок залишиться активним і PROTOCOL_CONNECTION_LOSTне відбуватиметься.

Крім того, цей метод гарантує, що ви підтримуєте той самий зв’язок , на відміну від повторного підключення. Це важливо. Подумайте, що могло б статися, якби ваш сценарій покладався LAST_INSERT_ID()і підключення mysql було скинуто, не знаючи про це?

Однак це лише гарантує, що час очікування ( wait_timeoutта interactive_timeout) підключення не відбудеться. Це не вдасться, як очікувалося, в усіх інших сценаріях. Тому обов’язково обробляйте інші помилки.


1
Просто цікаво, куди б ви поставили цей запит db? Внизу сервера nodejs правильно? Єдина проблема полягає в тому, що я використовую mysql лише один раз для автентифікації користувача, а потім я зберігаю їх дані в тимчасовому об’єкті користувачів для моєї RPG-гри. Я не знаю, чому я сьогодні випадково отримав цю помилку закритого mysql, хм. Я замикаю з'єднання належним чином тощо.
NiCk Newman

1
Вам слід підключитися до бази даних і відключити за запитом. Це рішення призначене для служб, які постійно працюють і постійно використовують підключення до бази даних.
Гаджус

1
І те, і інше не звучить вірогідно, враховуючи, що ваш код слідує описаному шаблону (щось подібне до gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Якби це траплялося лише один-два рази з тисячі запитів, я б припустив проблеми з підключенням, перевантаження сервера чи щось подібне.
Гаджус

2
Це, мабуть, була найгіршою пропозицією! Людина, яка пропонує вам забити базу даних запитами лише для того, щоб з'єднання не перестало працювати? Що станеться, якщо це зробить 100 людей? або чому б не 10000, якщо ваш додаток не відзначає, потік слід повернути в пул потоків MYSQL, НЕ затягуючи потік, щоб ваш слабкий код не зламався !, в цьому випадку ви реалізуєте функціонал для повторного підключення, якщо така подія сталася ! Це неймовірно, це така сту *** слава богу, що у FB не було вас як провідного архітектора !!
Патрік Форсберг,

2
Я оновив відповідь, щоб засвідчити, що я не рекомендую такий підхід. Дякую за голови Патріку.
Гаджус,


3

кращим рішенням буде використання пулу - це погано впорається з вами.

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


1

Створення та руйнування з'єднань у кожному запиті може бути складним, у мене були головні болі при міграції сервера, коли я вирішив встановити MariaDB замість MySQL. З якоїсь причини у файлі etc / my.cnf параметр wait_timeout мав значення за замовчуванням 10 секунд (це спричиняє неможливість реалізації постійності). Потім рішення було встановлено на 28800, це 8 годин. Ну, я сподіваюсь допомогти комусь із цією "güevonada" ... вибачте за мою погану англійську.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.