Server NodeJs crashes in idle time and how do I fix it? - mysql

My server api is on alwayse alwaysdata.
After x time the server crash.
events.js:183
throw er;
// Unhandled 'error' eventError: Connection lost: The server closed the connection.
at Protocol.end (/home/ec2-user/node_modules/mysql/lib/protocol/Protocol.js:112:13)
at Socket.<anonymous> (/home/ec2-user/node_modules/mysql/lib/Connection.js:97:28)
at Socket.<anonymous> (/home/ec2-user/node_modules/mysql/lib/Connection.js:502:10)
at emitNone (events.js:111:20)
at Socket.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
at process._tickCallback (internal/process/next_tick.js:181:9)
I'm looking at whether this could not be related to a mysql error. but pre-existing posts do not help me. I think the server mysql cut the connection I do not know why.
here I establish the connection:
let con = mysql.createConnection({
host: "alwaysdata.net",
user: "user",
password: "",
database: "database"
});
try {
con.query(check, (err, customer) => {
if (err){
console.log("%s Error on check query",Date());
throw err;
}

try connection pool:
const mysql = require('mysql');
let pool = mysql.createPool(
{
connectionLimit : 100,
host : '172.17.0.1',
port : 3306,
user : 'test',
password : 'test',
database : 'test',
multipleStatements: true
}
);
...
pool.query(sql, params, function(err, rows) {
...
it works stably on my versions of mysql 5.7 and 8

I believe there are two ways you can handle this.
1) Force MySQL to keep the connection alive (not official, but I believe will do the trick).
2) Handle the mysql server disconnect from the Node's point of
view.
For both there is an excellent example here.
Server disconnects
You may lose the connection to a MySQL server due to network problems,
the server timing you out, the server being restarted, or crashing.
All of these events are considered fatal errors, and will have the
err.code = 'PROTOCOL_CONNECTION_LOST'. See the Error Handling section
for more information.
Re-connecting a connection is done by establishing a new connection.
Once terminated, an existing connection object cannot be re-connected
by design.
With Pool, disconnected connections will be removed from the pool
freeing up space for a new connection to be created on the next
getConnection call.

let connection=null;
function handleDisconnect() {
connection = mysql.createConnection({
host: "alwaysdata.net",
user: "user",
password: "",
database: "database"
}); // 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();
setInterval(function () {
connection.query('SELECT 1');
}, 5000);
module.exports = connection;
you export the connection object and use this for the other connection queries.
I have called a Query every 5sec to keep the connection alive, i have tried all other approaches and this works like a charm.

Manish's answer worked for me!
I've been struggling with this for the past two days. I had a nodejs server with mysql db running on my localhost and after migrating to heroku with cleardb addon I came across several issues. I had this code in a config file:
const mysql = require('mysql');
const db = mysql.createConnection({
host: 'host',
database: 'database',
user: 'user',
password: 'password', });
module.exports = db;
I changed it to what Manish mentioned to handle the disconnect.

Related

aws linux server crashing after deployment

I have been running my reactJS website for about one year so far and there's server crashing happened(this start to happen in the last 3 months) when each time I did a deployment(after doing the deployment it works fine but) & on the next day morning when I tried to log in to my website I couldn't access it & I have to restart my PM2 server to make it work again. but from last week my whole AWS instance crashed & I can't find why that happened, from last week this happened to me 2 times. then I have to go to AWS web and restart the server(before I have started using the console but since now I couldn't access it via console have to go to the AWS web and start it again).
also when 1st-time server crashing happens I got that my MySQL server closed the connection since I got it from the logs:
db error Error: Connection lost: The server closed the connection. at Protocol.end (/home/ubuntu/CIAO_ERP/node_modules/mysql/lib/protocol/Protocol.js:112:13) at Socket.<anonymous> (/home/ubuntu/CIAO_ERP/node_modules/mysql/lib/Connection.js:94:28) at Socket.<anonymous> (/home/ubuntu/CIAO_ERP/node_modules/mysql/lib/Connection.js:526:10) at Socket.emit (events.js:215:7) at Socket.EventEmitter.emit (domain.js:475:20) at endReadableNT (_stream_readable.js:1184:12) at processTicksAndRejections (internal/process/task_queues.js:80:21) { fatal: true, code: 'PROTOCOL_CONNECTION_LOST' }
then I have used this solution :stackoverflow answer for handling 'PROTOCOL_CONNECTION_LOST'
then I handled that issue but still, a connection loss appears.
anyway, I'm attaching my connection handling and my server code segments to check whether if I did anything wrong!
SERVER.js
const express = require("express");
const cors = require("cors");
const { DBConnect } = require("./connection");
DBConnect();
const path = require("path");
const app = express();
app.use(express.json({ limit: "50mb", extended: true }));
app.use(
express.urlencoded({ limit: "50mb", extended: true, parameterLimit: 50000 })
);
app.use(cors());
app.use("/api/users", require("./routes/api/users"));
app.use("/api/invoiceSetting", require("./routes/api/InvoiceSetting"));
app.use("/api/auth", require("./routes/api/auth"));
app.use("/api/appSetting", require("./routes/api/AppSetting"));
app.use("/api/StakeHolder", require("./routes/api/StakeHolderSetting"));
app.use("/api/warehouse", require("./routes/api/WarehouseSetting"));
app.use("/api/production", require("./routes/api/ProductionSetting"));
app.use("/api/purchasing", require("./routes/api/Purchasing"));
app.use("/api/purchasingTemp", require("./routes/api/PurchasingTemp"));
//serve static assets if in production
app.use(express.static(path.join(__dirname, "../..", "build")));
const port = process.env.PORTADDRESS || 5000;
app.listen(port, () => console.log(`listening on http://localhost:${port}`)).on(
"error",
(err) => {
console.log(`catched error on listen & error is ${err}\n`);
}
);
here is my DB connection handling code
const mysql = require("mysql");
require("dotenv").config();
let portDB = process.env.PORT_DB;
console.log("PORT ENV VARIABLE:", portDB);
if (portDB === undefined) {
process.exit();
}
var db_config = {
host: process.env.HOST_NAME,
user: process.env.USER_NAME,
password: process.env.PASSWORD,
database: process.env.DATABASE,
multipleStatements: true,
port: portDB,
};
let db = mysql.createConnection(db_config);
const handleDisconnect = () => {
db = mysql.createConnection(db_config);
db.connect((err) => {
// The server is either down
if (err) {
// or restarting (takes a while sometimes).
console.log("error when connecting to db:", err);
console.log("& restarting");
setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
} // to avoid a hot loop, and to allow our node script to
else {
console.log("Connected Mysql DB!");
}
}); // process asynchronous requests in the meantime.
// If you're also serving http, display a 503 error.
db.on("error", (err) => {
console.log("db error", err);
if (err.code === "PROTOCOL_CONNECTION_LOST") {
console.log(`err.code : PROTOCOL_CONNECTION_LOST appeard\n`);
// Connection to the MySQL server is usually
handleDisconnect(); // lost due to either server restart, or a
} else {
// connnection idle timeout (the wait_timeout
console.log(`db.on("error") else called & err : ${err}\n`);
throw err; // server variable configures this)
}
});
};
module.exports = {
db: db,//this db is used to handling mysql queries
DBConnect: handleDisconnect,//this is used to start the db
};
I would be glad if any help me to solve this server crashing problem or whole AWS instance crashing problem I'm facing right now :(

DB Error: connection lost: server Closed the connection

I'm facing this error when the there are no requests to mysql it goes to idles state and we face this db error. I'm working with node, mysql deployed onto openshift cluster.
How do I keep the db connection alive such that the server never closes the connection?
PFA
Please, lemme know is there any solutions? I'm stuck for past 2 weeks
Update -
Following is the code I'm using
`var connection;
function handleDisconnect() {
connection = mysql.createConnection({
host: config.db.host,
user: config.db.user,
password: config.db.password,
database: config.db.database,
port: config.db.port,
}); // 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();`
Since, you are using Node.js, you could use the connection pool.
pooling-connections
Below is a snippet from the link. Notice, connection.release(); It doesn't destroy the connection, but allows the connection to be used again.
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit : 10,
host : 'example.org',
user : 'bob',
password : 'secret',
database : 'my_db'
});
pool.getConnection(function(err, connection) {
if (err) throw err; // not connected!
// Use the connection
connection.query('SELECT something FROM sometable', function (error, results, fields) {
// When done with the connection, release it.
connection.release();
// Handle error after the release.
if (error) throw error;
// Don't use the connection here, it has been returned to the pool.
});
});

Node MySQL Connection Pool - wait for database to start

How do I check if a MySQL database is ready for some queries from a Node MySQL Connection Pool?
I have a Docker environment consisting of thee containers:
container 1: web server
container 2: api
container 3: database
The database container runs a MySQL database. The api container connects to that database. All three containers are started at the same time. The web server container is up after 0,5s. The api container is up after 2s. The database server is up after 20s.
Currently, the api tries to access the tables of the database before the database is up and running. This leads to errors like connection refused. The following code segment always ends up with the message "Error querying database!" when the MySQL database is not yet up:
const sql: string = 'SELECT * FROM sometable;';
MySQL.createPool({
connectionLimit: 10,
acquireTimeout: 30000,
waitForConnections: true,
database: 'mydatabase',
host: 'localhost',
multipleStatements: true,
password: 'mypassword',
user: 'root',
}).query(sql, (err, result) => {
if (result) {
console.log('Successfully queried database.');
} else {
console.log('Error querying database!');
}
});
Versions in use:
OS: Ubuntu 19.10
Node: v13.6.0
MySQL (Node API): "#types/mysql": "2.15.8" and "mysql": "2.17.1"
MySQL (Docker Database): mysql:5.7.28
TypeScript: 3.7.4
I would like to check (and wait) the database readiness out of the api, possibly using the Connection Pool I use for queries. Is that possible?
Retry to connect with setTimeout():
(answer in Javascript rather than typescript)
'use strict';
const dbpool = require('mysql').createPool({
connectionLimit: 10,
acquireTimeout: 30000,
waitForConnections: true,
database: 'mydatabase',
host: 'localhost',
multipleStatements: true,
password: 'mypassword',
user: 'root',
});
const sql = 'SELECT * FROM sometable;';
const attemptConnection = () =>
dbpool.getConnection((err, connection) => {
if (err) {
console.log('error connecting. retrying in 1 sec');
setTimeout(attemptConnection, 1000);
} else {
connection.query(sql, (errQuery, results) => {
connection.release();
if (errQuery) {
console.log('Error querying database!');
} else {
console.log('Successfully queried database.');
}
});
}
});
attemptConnection();
Here is my test run:
$ sudo service mysql stop; node test.js & sudo service mysql start
[1] 24737
error connecting. retrying in 1 sec
error connecting. retrying in 1 sec
$ Successfully queried database.
FYI, The program never ends because it needs dbpool.end();
Your API should try to connect to the database with a timeout and a certain threshold of connection attempts. However, there are readily available solutions for this scenario.
Try using wait-for-mysql module.
waitForMy = require 'wait-for-mysql'
config =
username: user
password: pass
quiet: true
query: 'SELECT 1'
waitForMy.wait(config)
Here you have a variation but with no need to mysql pooling. I'm using this on my server and it does work:
const mysql = require('mysql')
var db // global, to use later to db.query
var dbInfo = {
host : 'example.org',
database : 'some_database',
user : 'bob',
password : 'secret'
}
function connectToDb(callback) {
const attemptConnection = () => {
console.log('Attempting to connect to db')
dbInfo.connectTimeout = 2000 // same as setTimeout to avoid server overload
db = mysql.createConnection(dbInfo)
db.connect(function (err) {
if (err) {
console.log('Error connecting to database, try again in 1 sec...')
db.destroy() // end immediately failed connection before creating new one
setTimeout(attemptConnection, 2000)
} else {
callback()
}
})
}
attemptConnection()
}
// now you simply call it with normal callback
connectToDb( () => {
console.log('Connection successfully')
// do some queries
db.query(..)
})

Nodejs, mysql 'connection lost the server closed the connection'

I connected mysql to nodejs. After a certain period of time, you will get the error :
'Connection lost the server closed the connection'.
I need your help.
An error has occurred and we added the function handleDisconnect. However, once a disconnect is resolved, the second error occurs again from Connection lost the server closed the connection.
I wonder why it should be only once and not the second one.
ps: The description may not be smooth using a translator.
This is part of the app.js file
// connection to databases
var mysql_dbc = require('./config/db_con')();
var connection = mysql_dbc.init();
mysql_dbc.test_open(connection);
// Added Code
handleDisconnect(connection);
function handleDisconnect(client) {
client.on('error', function (error) {
if (!error.fatal) return;
if (error.code !== 'PROTOCOL_CONNECTION_LOST') throw err;
console.error('> Re-connecting lost MySQL connection: ' + error.stack);
mysql_dbc.test_open(connection);
});
};
You can try to use this code to handle server disconnect:
var mysql = require("mysql");
var configuration = {
host: "localhost",
user: "root",
password: "mysql",
database: "blog"
};
var connection;
function handleDisconnect() {
connection = mysql.createConnection(configuration);
connection.connect(function(err) {
if (err) {
console.log("error when connecting to db:", err);
setTimeout(handleDisconnect, 2000);
}else{
console.log("connection is successfull");
}
});
connection.on("error", function(err) {
console.log("db error", err);
if (err.code === "PROTOCOL_CONNECTION_LOST") {
handleDisconnect();
} else {
throw err;
}
});
}
handleDisconnect();
You may lose the connection to a MySQL server due to network problems,
the server timing you out, the server being restarted, or crashing.
All of these events are considered fatal errors.
Re-connecting a connection is done by establishing a new connection.
Once terminated, an existing connection object cannot be re-connected by design.
With Pool, disconnected connections will be removed from the pool freeing up space for a new connection to be created on the next getConnection call.

Handle Disconnect Express JS Throw Error Access Denied for user localhost

hello i'm trying to handle disconnect my server express js , i'm using this code of handle disconnect , and it throws error access denied for user in localhost.
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();
and my connection host
var mysql = require('mysql');
var db_config = module.exports = {
'connection': {
'host': 'localhost',
'user': 'root',
'password': ''
},
'database': 'database'
};
and it happends on my server also which is throwing error like access denied for user localhost.
the error shows like this
Error: ER_DBACCESS_DENIED_ERROR: Access denied for user ''#'localhost' to database 'databases'
The error message is telling the empty user (at) localhost is not allowed.
That leads me to the db_config:
Replace db_config with db_config.connection in the code line
connection = mysql.createConnection(db_config.connection);