nodejs + mysql: how can i reopen mysql after end()? - mysql

code as follows:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
port :"3306",
database :"mydb",
user : 'root',
password : '007007',
});
var isCon = true;
connection.connect(
function (err) {
console.log(isCon);
if (err) {
isCon=false;
console.error("error connecting :"+err);
return;
};
}
);
if(isCon){
connection.query('select * from tb_items', function(err, result) {
if (err) throw err;
console.log('The solution is: ', result);
console.log('The typeof solution is ',typeof(result));
debugger;
});
connection.end();
}
connection.connect(
function (err) {
console.log(isCon);
if (err) {
isCon=false;
console.error("error connecting :"+err);
return;
};
}
);
if(isCon){
connection.query('select * from tb_items', function(err, result) {
if (err) throw err;
console.log('The solution is: ', result);
console.log('The typeof solution is ',typeof(result));
debugger;
});
connection.end();
}
i just open()-->connect()-->query()-->end(),then did it again,but second time , there is a error : Error:Could not enqueue Handshake after invoking quiting .
question : maybe i can't reopen it after end().but i just wanna kwon ,if i end(),how can i reopen it?

no, you can't, just create another one. All state in the connection class only relevant for current connection, so having "reopenWithSameConfig" method is possible, but you should really do this from outside.
Also, you don't need to close connection on each query - just continue to reuse it without calling .end()
If you want multiple connections and automatic disposal of dead connections you should use Pool class.
One more note: your isCon check is incorrect, connection.query is called before connect() callback so it's always true. It's safe to just check error in query callback itself. If connection was not successful error is propagated to a queued command

Related

connection.query(...).then is not a function

I am new to the node js . I am using node with express in my backend and mysql as database . I have the confusion while handling the async calling . In my code while i use .
return connection.query(qry).then(
function(result) {
console.log('Query executed');
resolve(result.rows[0]);
},
function(err) {
console.log('Error occurred', err);
reject(err);
}
)
I got error connection.query(...).then is not a function
connection.query(qry, function (err, rows, fields) {
});
is executed correctly.
Simple query i am not getting any problem . while execute the complex query the above one is not wait for complete query execution
To use .then() with mysql first you need to “promisify” the database client.That can be done by creating a wrapper class for the MySQL client.
Check this article for better understanding
I have not found that, we can use promise with connection.query('') function. As per mysqljs documentation we can pass callback function for getting result.
var mysql = require('mysql');
var connection = mysql.createConnection(...);
connection.query('SELECT * FROM table_name', function (error, results, fields) {
if (error) throw error;
console.log(result);
});
You need to import mysql, and also actually create the connection.
Just do:
var mysql=require('mysql');
var connection=mysql.createConnection({
host:'127.0.0.1',
port: '3306',
user:'root',
password:'12345',
database:'db'
});
connection.connect(function(error){
if(!!error){
console.log(error);
}else{
console.log('Connected!:)');
}
});

Node.JS and MySQL - queries lock up and execute extremely slowly

I am getting strange behavior using Node.JS and MySQL with this driver - https://github.com/mysqljs/mysql
Essentially, I have a button on the frontend that triggers an app.get that makes a query in the database and I can happily use the results in my backend.
This works nicely, until I press the button 4-5 times in a second, where as the queries lock up and I have to wait for 2-3 minutes until they continue executing. I have a similar write function that behaves the same way.
Is it possible this is a problem, because I'm trying to execute the exact same query asynchronously? I.e. do I have to limit this from the front end or is it a backend problem?
Any ideas on how to debug what exactly is going on?
// database.js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit: 100,
host : 'localhost',
user : 'secret',
password : 'secret',
database : 'mydb'
});
exports.getConnection = function(callback) {
pool.getConnection(function(err, connection) {
callback(err, connection);
});
};
// dbrw.js
var con = require('../config/database');
function read(id, done) {
con.getConnection(function(err, connection){
if(!err){
connection.query("SELECT * FROM users WHERE id = ?",[id], function(err, rows) {
connection.release();
if (err)
done(err);
if (rows.length) {
console.log("rows " + JSON.stringify(rows));
done(rows[0].progress);
};
});
}
else {
console.log(err);
}
});
}
exports.read = read;
// routes.js
var dbrw = require('./dbrw.js');
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
});
});
// Frontend - angular app.js
$scope.tryread = function() {
$http.get('/read');
}
Thanks in advance for any input.
I see a few issues:
function read(id, done) {
con.getConnection(function(id, connection){...}
}
Notice how you overwrite the id passed to read by giving that same name to an argument of the callback to getConnection.
Also, your Express route doesn't actually end the request by sending back a response, which will make your browser time out the connection. At some point, it will even refuse to send more requests because too many are still pending.
So make sure to end the request:
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
res.end(); // or `res.send(result)`
});
});
And a tip: you should use the callback calling convertion for Node, where the first argument represents an error (if there is any) and the second argument represents the return value.

NodeJS: How to stop code execution till create operation to MySQL completes

I have a very basic scenario, I am making a create operation call to MySQL in my NodeJS application. Once I get result of create operation (success or failure) I have to execute some code.
But now due to asynchronous behavior of NodeJS my code which is dependent on result MySQL create operation is getting executed before MySQL create operation sends results back.
Here is my code
calculation.js
var mysql = require("mysql");
var methods = {};
// Creating connection
methods.executeQuery = function(selectQuery, values){
var result;
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "*********",
database: "******"
});
// getting connection
con.connect(function(err){
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Connection established');
});
con.query(selectQuery, values, function(err,rows){
if(err) throw err;
console.log(rows);
result = rows;
console.log(result);
return result;
});
}
module.exports = methods;
client.js
var execute = require("./calculate.js");
var selectQuery = 'INSERT INTO users (username,password) VALUES (?,?)';
var values = ['sohamsoham12','sohamsoham12'];
var insertedRowInfo = execute.executeQuery(selectQuery, values);
if(insertedRowInfo){
console.log("true");
}else{
console.log("false");
}
I don't know if I correctly understand your question (what is the "create operation", for example?). But...
You can try this solution: execute the query inside the connect success callback:
// getting connection and executing query
con.connect(function(err){
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Connection established');
con.query(selectQuery, values, function(err,rows){
if(err) throw err;
console.log(rows);
result = rows;
console.log(result);
return result; // this can't work... you should invoke a callback function, here...
});
});
UPDATE:
After OP comment, I now fully understand the question... (sorry :-().
You just miss a bit of async behavior... :-)
You should simply change methods.executeQuery from
function(selectQuery, values) {
...
}
to
function(selectQuery, values, callback) {
...
}
Then, instead using
return result;
You should simply use
callback(err, result); // if any error occurred
or
callback(null, result); // if no error occurred
Then, in client.js, when calling the executeQuery method, instead of
var insertedRowInfo = execute.executeQuery(selectQuery, values);
You should simply do
execute.executeQuery(selectQuery, values, function(err, insertedRowInfo) {
if (err) {
// handle error
} else {
// handle success, using insertedRowInfo...
}
});

Node.js MySQL Needing Persistent Connection

I need a persistent MySQL connection for my Node web app. The problem is that this happens about a few times a day:
Error: Connection lost: The server closed the connection.
at Protocol.end (/var/www/n/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:895:16
at process._tickCallback (node.js:415:13)
error: Forever detected script exited with code: 8
error: Forever restarting script for 2 time
info: socket.io started
Here is my connection code:
// Yes I know multipleStatements can be dangerous in the wrong hands.
var sql = mysql.createConnection({
host: 'localhost',
user: 'my_username',
password: 'my_password',
database: 'my_database',
multipleStatements: true
});
sql.connect();
function handleDisconnect(connection) {
connection.on('error', function(err) {
if (!err.fatal) {
return;
}
if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
throw err;
}
console.log('Re-connecting lost connection: ' + err.stack);
sql = mysql.createConnection(connection.config);
handleDisconnect(sql);
sql.connect();
});
}
handleDisconnect(sql);
As you can see, the handleDisconnect code does not work..
Use the mysql connection pool. It will reconnect when a connection dies and you get the added benefit of being able to make multiple sql queries at the same time. If you don't use the database pool, your app will block database requests while waiting for currently running database requests to finish.
I usually define a database module where I keep my queries separate from my routes. It looks something like this...
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'example.org',
user : 'bob',
password : 'secret'
});
exports.getUsers = function(callback) {
pool.getConnection(function(err, connection) {
if(err) {
console.log(err);
callback(true);
return;
}
var sql = "SELECT id,name FROM users";
connection.query(sql, [], function(err, results) {
connection.release(); // always put connection back in pool after last query
if(err) {
console.log(err);
callback(true);
return;
}
callback(false, results);
});
});
});
I know this is super delayed, but I've written a solution to this that I think might be a bit more generic and usable. I had written an app entirely dependent on connection.query() and switching to a pool broke those calls.
Here's my solution:
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'localhost',
user : 'user',
password : 'secret',
database : 'test',
port : 3306
});
module.exports = {
query: function(){
var sql_args = [];
var args = [];
for(var i=0; i<arguments.length; i++){
args.push(arguments[i]);
}
var callback = args[args.length-1]; //last arg is callback
pool.getConnection(function(err, connection) {
if(err) {
console.log(err);
return callback(err);
}
if(args.length > 2){
sql_args = args[1];
}
connection.query(args[0], sql_args, function(err, results) {
connection.release(); // always put connection back in pool after last query
if(err){
console.log(err);
return callback(err);
}
callback(null, results);
});
});
}
};
This instantiates the pool once, then exports a method named query. Now, when connection.query() is called anywhere, it calls this method, which first grabs a connection from the pool, then passes the arguments to the connection. It has the added effect of grabbing the callback first, so it can callback any errors in grabbing a connection from the pool.
To use this, simply require it as module in place of mysql. Example:
var connection = require('../middleware/db');
function get_active_sessions(){
connection.query('Select * from `sessions` where `Active`=1 and Expires>?;', [~~(new Date()/1000)], function(err, results){
if(err){
console.log(err);
}
else{
console.log(results);
}
});
}
This looks just like the normal query, but actually opens a pool and grabs a connection from the pool in the background.
In response to #gladsocc question:
Is there a way to use pools without refactoring everything? I have
dozens of SQL queries in the app.
This is what I ended up building. It's a wrapper for the query function. It will grab the connection, do the query, then release the connection.
var pool = mysql.createPool(config.db);
exports.connection = {
query: function () {
var queryArgs = Array.prototype.slice.call(arguments),
events = [],
eventNameIndex = {};
pool.getConnection(function (err, conn) {
if (err) {
if (eventNameIndex.error) {
eventNameIndex.error();
}
}
if (conn) {
var q = conn.query.apply(conn, queryArgs);
q.on('end', function () {
conn.release();
});
events.forEach(function (args) {
q.on.apply(q, args);
});
}
});
return {
on: function (eventName, callback) {
events.push(Array.prototype.slice.call(arguments));
eventNameIndex[eventName] = callback;
return this;
}
};
}
};
And I use it like I would normally.
db.connection.query("SELECT * FROM `table` WHERE `id` = ? ", row_id)
.on('result', function (row) {
setData(row);
})
.on('error', function (err) {
callback({error: true, err: err});
});

Application does not terminate with MySQL pool

I am writing a nodejs application and want to use connection pooling.
However, the following application does not terminate - although I would expect it to terminate after the call to connection.end()
Application works just fine, if I use one connection instead of the pool. Do I need to terminate the pool in some way?
Library used: https://github.com/felixge/node-mysql
node.js version: 0.10.4 on Ubuntu
var mysql = require('mysql');
var pool = mysql.createPool({
host : 'example.org',
user : 'myuser',
password : 'youbet',
database : 'notrevealingdetails',
insecureAuth: true
});
function getCampaignData(callback)
{
pool.getConnection(function(err, connection) {
if(err) throw err;
connection.query(
'SELECT cam.id, cam.name AS campaign_name, cam.subdomain, usr.email, usr.display_name AS user_displayname ' +
'FROM campaigns AS cam INNER JOIN users AS usr ON usr.id = cam.user_id ' +
'WHERE cam.state=2',
function(err, rows) {
callback(err, rows,connection);
//console.log('called end()');
}); // callback function for connection.query
}); // end pool.GetConnection
}
getCampaignData(function(err, rows, connection) {
if (err) throw err;
connection.end();
console.log("I expect my app to terminate");
});
I was having the very same problem, but looking at the source code
https://github.com/felixge/node-mysql/blob/master/lib/Pool.js
I found that the pool, at least in its current implementation, has an end() method that is turns call end() on all connections.
It also accept a callback function to be called after all connections are actually ended (or whenever an error occur).
pool.end(function (err) {
if (err) console.error("An error occurred: " + err);
else console.log("My app terminated");
});
I would use
getCampaignData(function(err, rows, connection)
{
if (err) throw err;
connection.release();
console.log("I expect my app to terminate");
});