Connection timed out when using connection pooling - mysql

I get the following error when I get a connection object from a connection pool. It works sometimes but sometimes I get an error and the connection is undefined. I don't think I am supposed to get a connection timeout error because I'm using connection pool and in a connection pool you already have a few connections and you're not creating a new connection.
Can someone tell me how to handle this error and connect again.
The error at getConnection
{ [Error: connect ETIMEDOUT]
errorno: 'ETIMEDOUT',
code: 'ETIMEDOUT',
syscall: 'connect',
fatal: true }
The code:
var pool = mysql.createPool({
connectionLimit : 100, //important
host : '192.168.2.2',
user : 'testmysql',
password : 'test123',
database : 'tollsystem',
debug : false
});
I get the error here while using the pooled object:
app.get('/getClientList',function(req,res){
var data={
"error":1,
"clients":""
};
pool.getConnection(function(err,connection){
console.log(err);
connection.query("select * from mstrclient",function(err,rows,fields){
if(rows.length !=0){
res.json(rows);
}else{
data["error"]=1;
data["clients"]="no details found";
res.json(data);
}
connection.release();
})
});
});
The error:
connection.query("select * from mstrclient",function(err,rows,fields){
^
TypeError: Cannot read property 'query' of undefined
at D:\abhilash\Projects\Toll main aHosted\TollMain\server.js:415:15
at Handshake.onConnect (D:\abhilash\Projects\Toll main aHosted\TollMain\node
_modules\mysql\lib\Pool.js:58:9)
at Handshake.Sequence.end (D:\abhilash\Projects\Toll main aHosted\TollMain\n
ode_modules\mysql\lib\protocol\sequences\Sequence.js:85:24)
at D:\abhilash\Projects\Toll main aHosted\TollMain\node_modules\mysql\lib\pr
otocol\Protocol.js:399:18
at Array.forEach (native)
at D:\abhilash\Projects\Toll main aHosted\TollMain\node_modules\mysql\lib\pr
otocol\Protocol.js:398:13
at nextTickCallbackWith0Args (node.js:420:9)
at process._tickCallback (node.js:349:13)

Related

Facing issue with mysql database with node js

i have created express app with mysql database.
when i call mysql query it works fine and then i call my view. loading view take few minute(2-3 min) and app crashed with bellow error.
events.js:287
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at TCP.onStreamRead (internal/stream_base_commons.js:205:27)
Emitted 'error' event on Connection instance at:
at Connection._handleProtocolError (C:\Users\AMW\Desktop\dishmize\dishmize\node_modules\mysql\lib\Connection.js:423:8)
at Protocol.emit (events.js:310:20)
at Protocol.EventEmitter.emit (domain.js:482:12)
at Protocol._delegateError (C:\Users\AMW\Desktop\dishmize\dishmize\node_modules\mysql\lib\protocol\Protocol.js:398:10)
at Protocol.handleNetworkError (C:\Users\AMW\Desktop\dishmize\dishmize\node_modules\mysql\lib\protocol\Protocol.js:371:10)
at Connection._handleNetworkError (C:\Users\AMW\Desktop\dishmize\dishmize\node_modules\mysql\lib\Connection.js:418:18)
at Socket.emit (events.js:310:20)
at Socket.EventEmitter.emit (domain.js:482:12)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3) {
errno: 'ECONNRESET',
code: 'ECONNRESET',
syscall: 'read',
fatal: true
}
[nodemon] app crashed - waiting for file changes before starting...
i already spend 8- 10 hours.
please help me to resolve this issue.
thanks
Update:
const options = {
user: config.get('MYSQL_USER'),
password: config.get('MYSQL_PASSWORD'),
database:config.get('DATABASE'),
host: config.get('HOST'),
port: 3306
}
const connection = mysql.createConnection(options);
connection.connect( function (err) {
if (err) {
console.log("!!! Cannot connect !!! Error:"); throw err;
} else {
console.log("Connection established.");
}
});
use below
const options = { connectionLimit :10, user:config.get('MYSQL_USER'), password: config.get('MYSQL_PASSWORD'), database:config.get('DATABASE'), host: config.get('HOST'), port: 3306 }
const connection_pool = mysql.createPool(options);
connection_pool.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
if (error) throw error;
console.log('The solution is: ', results[0].solution);
});
provide connectionLimit according to you use this is pool size of connection

Lambda function "Error: connect ETIMEDOUT" when receive too many requests for MySQL query

I am trying to do testing on my AWS lambda function which makes a query to RDS MySQL (t2.medium).
However, if I request the API a large number of times, although I can get query successfully with correct data, it sometimes results "Error: connect ETIMEDOUT".
Is there anything wrong in my code or setting?
I read some suggestions to set some parameters:
MySQL:
wait_timeout 1
max_connections 16000
interactive_timeout 6000
max_allowed_packet 1073741824
Lamdba:
Timeout 60 sec place the Lambda function in the same VPC as your RDS
Added VPC execution policy AWSLambdaVPCAccessExecutionRole
assign a security group to the lambda function
In the security attached to the RDS instance, added an inbound rule
for mysql
Confirm that Lambda function has access to the same VPC RDS database
Lambda Error Log
2019-03-28T18:51:47.353Z ab4fbbaf-1ea2-458b-a5b5-781cdfdd80df { Error:
connect ETIMEDOUT
at Connection._handleConnectTimeout
(/var/task/node_modules/mysql/lib/Connection.js:411:13)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:106:13)
at Socket.emit (events.js:208:7)
at Socket._onTimeout (net.js:420:8)
at ontimeout (timers.js:482:11)
at tryOnTimeout (timers.js:317:5)
at Timer.listOnTimeout (timers.js:277:5)
at Protocol._enqueue
(/var/task/node_modules/mysql/lib/protocol/Protocol.js:144:48)
at Protocol.handshake
(/var/task/node_modules/mysql/lib/protocol/Protocol.js:51:23)
at Connection.connect
(/var/task/node_modules/mysql/lib/Connection.js:118:18)
at Connection._implyConnect
(/var/task/node_modules/mysql/lib/Connection.js:453:10)
at Connection.query
(/var/task/node_modules/mysql/lib/Connection.js:198:8)
at Promise (/var/task/db.js:62:9)
at new Promise ()
at Object.retrieve (/var/task/db.js:55:10)
at exports.getAlerts (/var/task/index.js:59:24)
errorno: 'ETIMEDOUT',
code: 'ETIMEDOUT',
syscall: 'connect',
fatal: true }
RDS Error Log
2019-03-28T18:18:49.378320Z 9500 [Note] Aborted connection 9500 to db:
'db' user: 'user' host: '123.123.123.123' (Got timeout reading
communication packets)
2019-03-28T18:18:49.392514Z 9498 [Note] Aborted connection 9498 to db:
'db' user: 'user' host: '123.123.123.123' (Got timeout reading
communication packets)
2019-03-28T18:18:49.470617Z 9499 [Note] Aborted connection 9499 to db:
'db' user: 'user' host: '123.123.123.123' (Got timeout reading
communication packets)
2019-03-28T18:18:49.636775Z 9501 [Note] Aborted connection 9501 to db:
'db' user: 'user' host: '123.123.123.123' (Got timeout reading
communication packets)
2019-03-28T18:18:49.694669Z 9502 [Note] Aborted connection 9502 to db:
'db' user: 'user' host: '123.123.123.123' (Got timeout reading
communication packets)
2019-03-28T18:18:49.803457Z 9503 [Note] Aborted connection 9503 to db:
'db' user: 'user' host: '123.123.123.123' (Got timeout reading
communication packets)
2019-03-28T18:18:49.824250Z 9504 [Note] Aborted connection 9504 to db:
'db' user: 'user' host: '123.123.123.123' (Got timeout reading
communication packets)
My db.js query on lambda
const mysql = require('mysql')
let retrieve = (sql, objectArr, entityName) => {
return new Promise((resolve, reject) => {
let con = mysql.createConnection(dbParams)
con.query(sql, objectArr, (err2, results) => {
con.end()
if (err2) {
console.log(err2)
return reject(new apiError.DatabaseError('An error occurred in retrieve'))
}
console.log('Data retrieve successfully')
return resolve(results)
})
})
}
My test.js script
const request = require('request')
let errorCount = 0
let success = 0
for (let i = 0; i < 4000; i++) {
console.log('Send')
request.get('https://myapi/users', {
headers: {
'client_id': 'app',
'Content-Type': 'application/json'
}
}, (error, response, body) => {
if (error) {
console.log('some error')
errorCount++
} else {
let jsonBody = JSON.parse(body)
if (jsonBody.code === 0) {
success++
} else {
errorCount++
}
}
console.log('Success: ', success)
console.log('Error: ', errorCount)
})
}
Edit:
I also tried to change the i < 1 in test script, then it always gives me "Error: connect ETIMEDOUT. But with i < 900, it works successfully sometime
index.js
const db = require('./db.js')
exports.getUsers = async (event, context) => {
context.callbackWaitsForEmptyEventLoop = false
try {
let sql = 'SELECT * FROM User'
let abc = await db.retrieve(sql, [], 'user')
let response = {
statusCode: 200,
abc: abc,
code: 0
}
return response
} catch (err) {
console.log(err)
errorHandler(err)
}
}
db.js with Pool
const mysql = require('mysql')
const constants = require('./constants.js')
let dbParams = {
host: constants.SQL_CONNECTION_HOST,
user: constants.SQL_CONNECTION_USER,
password: constants.SQL_CONNECTION_PASSWORD,
database: constants.SQL_CONNECTION_DATABASE,
multipleStatements: true,
maxConnections: 4
}
const pool = mysql.createPool(dbParams)
let retrieve = (sql, objectArr, entityName) => {
return new Promise((resolve, reject) => {
pool.getConnection((err1, con) => {
if (err1) {
console.log(err1)
return reject(new apiError.DatabaseError('An error occurred in retrieve pool'))
}
console.log('Pool connect successfully')
con.query(sql, objectArr, (err2, results) => {
con.end()
if (err2) {
console.log(err2)
return reject(new apiError.DatabaseError('An error occurred in retrieve'))
}
console.log('Data retrieve successfully')
return resolve(results)
})
})
})
}
Error Log after used pool
2019-03-28T23:35:24.144Z 91b0fc78-e4d1-4fd9-bdf7-923715b165c0 { Error:
Handshake inactivity timeout
at Handshake.
(/var/task/node_modules/mysql/lib/protocol/Protocol.js:163:17)
at emitNone (events.js:106:13)
at Handshake.emit (events.js:208:7)
at Handshake._onTimeout
(/var/task/node_modules/mysql/lib/protocol/sequences/Sequence.js:124:8)
at Timer._onTimeout
(/var/task/node_modules/mysql/lib/protocol/Timer.js:32:23)
at ontimeout (timers.js:482:11)
at tryOnTimeout (timers.js:317:5)
at Timer.listOnTimeout (timers.js:277:5)
at Protocol._enqueue
(/var/task/node_modules/mysql/lib/protocol/Protocol.js:144:48)
at Protocol.handshake
(/var/task/node_modules/mysql/lib/protocol/Protocol.js:51:23)
at PoolConnection.connect
(/var/task/node_modules/mysql/lib/Connection.js:118:18)
at Pool.getConnection (/var/task/node_modules/mysql/lib/Pool.js:48:16)
at Promise (/var/task/db.js:72:10)
at new Promise ()
at Object.retrieve (/var/task/db.js:67:10)
at exports.getAlerts (/var/task/index.js:59:24)
code: 'PROTOCOL_SEQUENCE_TIMEOUT',
fatal: true,
timeout: 10000 }
Set with Pool now and test it with request loop:
i < 100 result => Success: 866 and Error: 134 requests.
i < 10 result => Success: 8 and Error: 2 requests.
Error with Handshake inactivity timeout
db.js with con.createConnection outside
const mysql = require('mysql')
// initialize dbParams
let con = mysql.createConnection(dbParams)
let retrieve = (sql, objectArr, entityName) => {
return new Promise((resolve, reject) => {
con.query(sql, objectArr, (err2, results) => {
//con.end() commet out connection end here
if (err2) {
console.log(err2)
return reject(new apiError.DatabaseError('An error occurred in retrieve'))
}
console.log('Data retrieve successfully')
return resolve(results)
})
})
}
It is not explained in the question how does the retrieve function is being called inside your lambda function.
Even though, it strongly seems that it will be executed for each iteration inside your test, which creates a very large number of connections and may explain the behavior you see.
I suggest creating the connection at lambda initialization time (aka 'coldstart'), by moving the code line let con = mysql.createConnection(dbParams) outside of any function (so that only a single connection will take place).
Another good option is to use connection pooling.

Connection lost The server closed the connection - Cannot enqueue Query after fatal error

I got an error once that the TCP connection is shut down by the server. The error looks the same as this question has
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)
So to solve this problem I used the answer posted in this question. I did this
var mysql = require('mysql');
var db_config = {
host : 'localhost',
user : 'xxxx',
password : 'xxxx',
database : 'xxxx'
}
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 {
console.log('error is err:', err); // connnection idle timeout (the wait_timeout
// throw err; // server variable configures this)
}
});
}
handleDisconnect();
module.exports = connection;
My program never crashes until today when I face some issue like user was not getting the notifications. since it has to do with the database. So when I checked the log files. this was the error
sql error isError: ER_QUERY_INTERRUPTED: Query execution was interrupted
db error { Error: Connection lost: The server closed the connection.
at Protocol.end (/var/www/html/mysite/node/node_modules/mysql/lib/protocol/Protocol.js:112:13)
at Socket.<anonymous> (/var/www/html/mysite/node/node_modules/mysql/lib/Connection.js:97:28)
at Socket.<anonymous> (/var/www/html/mysite/node/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:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9) fatal: true, code: 'PROTOCOL_CONNECTION_LOST' }
error when connecting to db: { Error: connect ECONNREFUSED 127.0.0.1:3306
at Object._errnoException (util.js:992:11)
at _exceptionWithHostPort (util.js:1014:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1186:14)
and then it keeps printing this above error in my log files and along with this as well
Cannot enqueue Query after fatal error.
Please help me to solve this problem. I have to do a restart the server to make it work

How to provide SERVICE_NAME in the connection options in mysql npm?

I have a JDBC connection string something like this
jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS_LIST=(LOAD_BALANCE=OFF)(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1711))(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1712)))(CONNECT_DATA=(SERVICE_NAME=servicename)(SERVER=DEDICATED)))
I have created the connection as
var connection = mysql.createConnection({
host: "hostname",
port: "1711",
user: "user",
password: "password"
});
How do I also provide SERVICE_NAME (like the jdbc string) to the connection options?
I am getting the following error without it:
Error: connect ECONNREFUSED <some_ip>:1711
at Object.exports._errnoException (util.js:1028:11)
at exports._exceptionWithHostPort (util.js:1051:20)
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1090:14)
--------------------
EDIT:
Changing the port to 1712 gives me a different error after taking a lot of time.
Error: Connection lost: The server closed the connection.
at Protocol.end (..\node_modules\mysql\lib\protocol\Protocol.js:113:13)
at Socket.<anonymous> (..\node_modules\mysql\lib\Connection.js:109:28)
at emitNone (events.js:91:20)
at Socket.emit (events.js:186:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
EDIT: Sorry. I didn't see the database was oracle and started trying mysql directly.
I am assuming that your mysql server is running on port 1711 not default port.
And if you are getting Connection lost error mean there are something wrong on your network try to reconnect your server after sometime.
var conn;
function handleDisconnect() {
conn = mysql.createConnection(//your config);
conn.connect(function(err) {
if(err) {
console.log('error when connecting to database:', err);
setTimeout(handleDisconnectConnection, 5000);
}
});
connection.on('error', function(err) {
console.log('db error', err);
if(err.code === 'PROTOCOL_CONNECTION_LOST') {
handleDisconnectConnection();
} else {
throw err;
}
});
}
handleDisconnectConnection();
Hope that will work for you

node-mysql implodes without doing anything

I am trying to simply connect to a mysql db, then close the connection. My code is basically taken straight from node-mysql's guide.
require('fs').readFile('/etc/mysql/mysql-ssl-ca-cert.pem','utf8',function(err,caFile){
if(err){
console.error(err);
}else{
var connection = require('mysql').createConnection({
host : 'localhost',
user : 'root',
password : 'password',
ssl : { ca : caFile }
});
connection.connect(function(err){
if(err){
console.error(err);
}else{
console.log('connected');
}
});
connection.end(function(err) { if(err) console.error('Error On DB Close.'); });
}
});
I get the 'connected' message but then everything crashes, triggered by an uncaught error exception, what did I do wrong?
backtrace:
events.js:85
throw er; // Unhandled 'error' event
^
Error: shutdown ENOTCONN
at exports._errnoException (util.js:746:11)
at Socket.onSocketFinish (net.js:232:26)
at Socket.emit (events.js:104:17)
at finishMaybe (_stream_writable.js:484:14)
at endWritable (_stream_writable.js:493:3)
at Socket.Writable.end (_stream_writable.js:459:5)
at Socket.end (net.js:407:31)
at Protocol.<anonymous> (/Users/camdennarzt/Developer/JS/barcoding/node_modules/mysql/lib/Connection.js:85:27)
at Protocol.emit (events.js:129:20)
at Protocol.end (/Users/camdennarzt/Developer/JS/barcoding/node_modules/mysql/lib/protocol/Protocol.js:99:10)
Turned out to be a bug in node or node-mysql. See https://github.com/felixge/node-mysql/issues/1027