nodejs mysql Ошибка: соединение потеряно Сервер закрыл соединение

89

когда я использую node 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();
jackieLin
источник

Ответы:

160

Попробуйте использовать этот код для обработки отключения сервера:

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 01
2
@jackieLin, вы можете смоделировать ситуацию, перезапустив службу mysql, на ubuntu sudo service mysql restart
игорь
1
Спасибо @ user3073745, эта проблема решена перезагрузкой
jackieLin
1
Отлично работает для node 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) не наступит. Как и ожидалось, во всех остальных сценариях он не сработает. Поэтому не забудьте обработать другие ошибки.

Gajus
источник
1
Просто любопытно, куда бы вы поместили этот запрос к базе данных? Внизу сервера nodejs, верно? Единственная проблема заключается в том, что я использую mysql только для однократной аутентификации пользователя, а затем сохраняю их данные во временном объекте пользователей для моей игры RPG. Я не знаю, почему сегодня я случайно получил эту ошибку mysql closed, хм. Я закрываю соединение должным образом и т. Д. Тоже.
NiCk Newman
1
Вы должны подключиться к базе данных и отключиться по запросу. Это решение предназначено для служб, которые работают непрерывно и постоянно используют соединение с базой данных.
Gajus
1
Это маловероятно, учитывая, что ваш код следует описанному шаблону (что-то похожее на gist.github.com/gajus/5bcd3c7ec5ddcaf53893 ). Если бы это произошло только один или два раза из тысяч запросов, я бы предположил проблемы с подключением, перегрузку сервера или что-то в этом роде.
Gajus
2
Возможно, это было худшее предложение! Человек, предлагающий забить базу данных запросами, чтобы соединение не разорвалось, не так ли? Что произойдет, если это сделают 100 человек? или почему не 10 000. Если ваше приложение этого не делает, поток должен быть возвращен в пул потоков MYSQL, НЕ забивая поток, чтобы ваш слабый код не сломался !, в этом случае вы реализуете функциональность для повторного подключения, если такое событие произошло ! Это невероятно, это так чертовски слава богу, что у FB не было тебя в качестве ведущего архитектора !!
Патрик Форсберг
2
Я обновил ответ, чтобы отразить, что я не рекомендую этот подход. Спасибо за внимание, Патрик.
Gajus
1

Создание и разрушение соединений в каждом запросе может быть сложным, у меня были некоторые проблемы с миграцией сервера, когда я решил установить MariaDB вместо MySQL. По какой-то причине в файле etc / my.cnf параметр wait_timeout имел значение по умолчанию, равное 10 секундам (это приводит к невозможности реализации сохранения). Тогда решение было установлено в 28800, это 8 часов. Что ж, я надеюсь помочь кому-нибудь с этой "гевонадой" ... извините за мой плохой английский.

Алекс Тауэрс
источник