No hint of errors when trying to connect to a database - mysql

I've been struggling to get MySQL working with node for a while. When I run the following code no errors are thrown, but simultaneously none of the console messages are being printed (except for the obvious one).
var app = require('express')();
var http = require('http').Server(app);
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '******',
database : 'blogDB'
});
connection.connect(function(err) {
if(err) {
console.log('error when connecting to database:', err);
}
console.log('Connected to the database');
});
var queryString = 'SELECT * FROM blogs';
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
for (var i in rows) {
console.log('Post: ', rows[i].id);
}
});
connection.end();
http.listen(3306, function(){
console.log('listening on *:3306');
});
Output:listening on *:3306
On top of this, when I go to "localhost:3306" in the browser, a download is immediately started and nothing appears on the web page. The download is a file with no extensions, but contained the following:
J
5.6.19 tscvKP3M ÿ÷ € g?F!q6X:Y2*z mysql_native_password ! ÿ„#08S01Got packets out of order
I am not sure if that is relevant, but it certainly was not happening when I was not running MySQL. I have no idea how to troubleshoot this. Any ideas what could be going wrong?

The error here is you're coding node.js as if it were procedural. It's not.
connection.connect(function(err) {
if(err) {
console.log('error when connecting to database:', err);
}
console.log('Connected to the database');
var queryString = 'SELECT * FROM blogs';
//change from connection to "this" because you're inside the context of the connection object now
this.query(queryString, function(err, rows, fields) {
if (err) throw err;
for (var i in rows) {
console.log('Post Titles: ', rows[i].id);
}
});
});
Node.js uses a series of callbacks that run when a task is completed. So when you want to do something AFTER you're connected to the DB, you run that code inside the callback.
What your code is doing is attempting to connect to the database, then while attempting to connect to the database you're querying a database you're not connected to, and so on and so forth.
For sake of illustrating the principle a little more, node functions use the following general methodology.
//1
myObj.myFunc( function( err , foo , bar ) {
//A
});
//2
myObj.myOtherFunc( function( err , someVar ) {
//B
});
1 will always run before 2. A and B may run in either order depending on when 1 and 2 finish executing. A will always run after 1 is done. B will always run after 2 is done.
Hopefully that helps clear things up ;)

As it turns out, MySQL and the app were running using the same port (3306). Changing the app's port to 3307 did the trick.

Related

How to debug an Azure Function using Node.js and mysql2 connecting to database

running into some issues trying to figure out an Azure Function (node.js-based) can connect to our mysql database (also hosted on Azure). We're using mysql2 and following tutorials pretty much exactly (https://learn.microsoft.com/en-us/azure/mysql/connect-nodejs, and similar) Here's the meat of the call:
const mysql = require('mysql2');
const fs = require('fs');
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.fname || (req.body && req.body.fname)) {
context.log('start');
var config = {
host:process.env['mysql_host'],
user: process.env['mysql_user'],
password: process.env['mysql_password'],
port:3306,
database:'database_name',
ssl:{
ca : fs.readFileSync(__dirname + '\\certs\\cacert.pem')
},
connectTimeout:5000
};
const conn = mysql.createConnection(config);
/*context.log(conn);*/
conn.connect(function (err) {
context.log('here');
if (err) {
context.error('error connecting: ' + err.stack);
context.log("shit is broke");
throw err;
}
console.log("Connection established.");
});
context.log('mid');
conn.query('SELECT 1+1',function(error,results,fields) {
context.log('here');
context.log(error);
context.log(results);
context.log(fields);
});
Basically, running into an issue where the conn.connect(function(err)... doesn't return anything - no error message, no logs, etc. conn.query works similarly.
Everything seems set up properly, but I don't even know where to look next to resolve the issue. Has anyone come across this before or have advice on how to handle?
Thanks!!
Ben
I believe the link that Baskar shared covers debugging your function locally
As for your function, you can make some changes to improve performance.
Create the connection to the DB outside the function code otherwise it will create a new instance and connect every time. Also, you can enable pooling to reuse connections and not cross the 300 limit that the sandbox in which Azure Functions run has.
Use the Promises along with async/await
You basically can update your code to something like this
const mysql = require('mysql2/promise');
const fs = require('fs');
var config = {
host: process.env['mysql_host'],
user: process.env['mysql_user'],
password: process.env['mysql_password'],
port: 3306,
database: 'database_name',
ssl: {
ca: fs.readFileSync(__dirname + '\\certs\\cacert.pem')
},
connectTimeout: 5000,
connectionLimit: 250,
queueLimit: 0
};
const pool = mysql.createPool(config);
module.exports = async function(context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.fname || (req.body && req.body.fname)) {
context.log('start');
const conn = await pool.getConnection();
context.log('mid');
await conn.query('SELECT 1+1', function(error, results, fields) {
context.log('here');
context.log(error);
context.log(results);
context.log(fields);
});
conn.release();
}
};
PS: I haven't test this code as such but I believe something like this should work
Debugging on serverless is challenging for obvious reasons. You can try one of the hacky solutions to debug locally (like Serverless Framework), but that won't necessarily help you if your issue is to do with a connection to a DB. You might see different behaviour locally.
Another option is to see if you can step debug using Rookout, which should let you catch the full stack at different points in the code execution and give you a good sense of what's failing and why.

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.

HTTP response code, response time, response length missing in Node.js / Express console output

I've got a little app that takes a request route in Node.js using Express, for example:
http://192.168.0.10:3000/db/
Here, /db/ is the route. This is fine, I have a db.js file that runs, it makes a call to a MySQL server that is expected to take a long time (possibly minutes) to return the results of a large join. Everything is okay if I make just a few requests now and then because I modified my settings for acceptable timeouts. I get results like the following on the Node.js console:
GET /db/ 200 88569.341 ms - 89
All gravy. However, now I'm using Apache Bench (I know it is not popular with everyone) to hammer the Node.js server and see what happens when I try and make lots of requests to the MySQL server (which is on a separate machine). If I use this technique to increase concurrent requests through Node.js to the MySQL server (on a separate machine), I start intermittently getting the following:
GET /db/ - - ms - -
I don't know what this means or how to use it, but I believe it means something bad is happening, because the time taken for a test run drops by 2/3 or so (~700 seconds to ~400 seconds or thereabouts) and console logging I added in my code is not being output enough times to indicate that every request is being serviced. Any tips on how to debug this to find out why some requests seem to be failing?
Note: the MySQL package I'm using is mysql, but I'm thinking that's not where the problem lies.
In case it helps, here is the code for my route. As a reminder, this code works at low concurrency. It also works without errors if I make the requests through Apache/PHP instead of Node.js.
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
/* GET users listing. */
router.get('/', function(req, res, next) {
// The code below borrowed in part from the NPM MySQL package documentation at:
// https://www.npmjs.com/package/mysql
var connection = mysql.createConnection({
host:/* my host */,
user:/* username */,
password:/* password */,
database:/* my db name */
});
connection.connect();
connection.query({sql:/* some huge join query */;',timeout:999999}, function(err, rows, fields) {
if (err) {
var output = "error! " + err;
console.log(output);
res.send(output);
}
else {
var output = "good: " + JSON.stringify(rows);
console.log(output);
res.send(output);
}
});
connection.end();
});
module.exports = router;
The #1 tip to debug heavy load is to make sure ALL possible error paths are handled and logged. connection.connect() and connection.end() both take callbacks that could report errors. And, just because you set one connection limit to 100,000 does not mean you've removed all limits on how many simultaneous connections the system might allow. There are often many different levels that limits may occur all the way from the library you are using to how it sits on the underlying OS.
I'd suggest that you create more robust logging so you can see if every request that started actually finished and to make sure all possible error paths have logging. When this runs, you should see "Matched requestCntrs" as one of the last log entries. If not, then some operation did not complete properly and an error was not logged.
var express = require('express');
var router = express.Router();
var mysql = require('mysql');
var requestCntrStart = 0;
var requestCntrDone = 0;
var requestCntrErr = 0;
/* GET users listing. */
router.get('/', function(req, res, next) {
// The code below borrowed in part from the NPM MySQL package documentation at:
// https://www.npmjs.com/package/mysql
++requestCntrStart;
var connection = mysql.createConnection({
host:/* my host */,
user:/* username */,
password:/* password */,
database:/* my db name */
});
// log any other errors
connection.on('error', function(err) {
++requestCntrErr;
console.log("Uncaught connection error: ", err.code); // 'ER_BAD_DB_ERROR'
logMatch();
});
function logMatch() {
if (requestCntrStart !== (requestCntrDone + requestCntrErr)) {
console.log("Unmatched requestCntrs: requestCntrStart = " + requestCntrStart +
", requestCntrDone = " + requestCntrDone + ", requestCntrErr = " + requestCntrErr);
} else {
console.log("Matched requestCntrs");
}
}
connection.connect(function(err) {
if (err) {
++requestCntrErr;
console.log("connection.connect() error: ", err);
logMatch();
}
});
connection.query({sql: 'some huge join query',timeout:999999}, function(err, rows, fields) {
if (err) {
++requestCntrErr;
var output = "connection.query() error! " + err;
console.log(output);
res.send(output);
logMatch();
}
else {
++requestCntrDone;
res.send(output);
logMatch();
}
});
connection.end(function(err) {
if (err) {
++requestCntrErr;
console.log("connection.end() error: ", err);
logMatch();
}
});
});
module.exports = router;

Why can't I send a response in Express from a mysql query?

I'll keep the code simple, but basically, I have a Node.js server running Express. Express is connected to a MySQL database using pooling (and the mysql npm package). This is what my server looks like (I left out the boring requires and whatnot to keep this simple). This is the only routing that the server handles.
server.all('/test', function (req, res, next) {
pool.getConnection(function (err, conn) {
if (err) {
console.log(err);
}
else {
conn.query("select * from spwp_appusers where id=46", function (err, rows) {
conn.release();
if (err) {
console.log(err);
}
else {
res.send(200);
}
});
}
});
next();
});
However, when I run this code, the server tries to execute res.send(200); but breaks and I get the following error:
/usr/lib/node_modules/mysql/lib/protocol/Parser.js:77
throw err; // Rethrow non-MySQL errors
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
Does anyone know what is happening? Why can't I send the response? Even when I use a callback, I get this error.
I think the problem is with next. try changing next(); inside getConnection()
above error show in my case mismatch my mysql user,password,db name so please check your mysql credential.
var pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'dbname', multipleStatements: true
});

How to query with node-mysql and write out the results?

I am trying to connect to a db on my hosting and write out the result, I am not getting any error, just blank space. line like console.log('test'); put at any place always work but I am not getting any query results, what am I doing wrong?
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'wm51.wedos.net',
user : 'xxxxxx',
password : 'xxxxxx',
database: 'd57283_vs'
});
connection.connect();
var queryString = 'SELECT * FROM versus LIMIT 5';
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
for (var i in rows) {
console.log(rows[i].title);
}
});
connection.end();
(The table is called versus, has columns title, url...in adminer it's all accessible and the query works...)
Be careful with that connection.end(); call at the bottom. NodeJS is asynchronous, remember?
Try putting that at the end of the inner function after the for-loop, otherwise it will get called as soon as the query is called, possibly killing the connection you're trying to use!
perhaps mysql-server is not to be connected, when you query,or mysql-server is to be closed when you query.
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'wm51.wedos.net',
user : 'xxxxxx',
password : 'xxxxxx',
database: 'd57283_vs'
});
connection.connect();
process.nextTick(function() {
var queryString = 'SELECT * FROM versus LIMIT 5';
connection.query(queryString, function(err, rows, fields) {
connection.end();
if (err) throw err;
for (var i in rows) {
console.log(rows[i].title);
}
});
});
I believe the connection.end() statement still needs to be after the for loop. Or else your ending the connection before the loop even starts.