i'm learning node and have hit an issue with running a mysql query. I am certain i am getting connectivity to the mysql db (as when i run the query from the same module as i connect to the DB i am able to print the rows to the console log). However i get a 500 error when i require the DB connection into my another file and use in the query. I've spent last few hours on stack overflow and still stuck. Its definitely not the function as if i just return text it works fine so its definitely something around the way i am utilising the db connection. The DB connection file is below:
// initialize database connection
const mysql = require('mysql')
var db;
function connectDatabase() {
if (!db) {
db = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_DATABASE
})
db.connect(function(err){
if(!err) {
console.log('Database is connected!')
} else {
console.log('Error connecting database!')
}
})
}
return db
}
module.exports = connectDatabase()
The module where the DB connection us used in query below:
const db = require('../db').connectDatabase
exports.getNightlyRatesData = () => {
//const { rows } = db.query('SELECT * FROM rate', function (err, rows) {
db.query('SELECT * FROM rate', function (err, rows) {
if (err) {
console.log("ERROR");
console.log(err);
return;
}
console.log("good");
})
return rows
}
Related
I have a Discord.js bot with a MySQL as a database. The problem I'm having is that the SQL stopped querying after a random amount of times, the only way that I could fix this is by restarting the node.js app
My bot involves a lot of sql querying inside of an sql query similar to :
sql.query(`SELECT xxxxx` , (err, res) => {
sql.query(`SELECT xxxxx`, (err, result) => {}
}
And my SQL pool code is :
const mysql = require('mysql');
const pool = mysql.createPool({
host : "localhost",
port : 3306,
user : "x",
password: "x",
database: 'x'
});
let sql = {};
sql.query = function(query, params, callback) {
pool.getConnection(function(err, connection) {
if(err) {
if (callback) callback(err, null, null);
return;
}
connection.query(query, params, function(error, results, fields) {
connection.release();
if(error) {
if (callback) callback(error, null, null);
return;
}
if (callback) callback(false, results, fields);
});
});
};
module.exports = sql;
My VPS is running fine, my SQL server is running fine as well. I'm not sure what's causing the problem.
My current solution is running a cronjob every 30 minutes to restart the application, I'm not sure if this is a good practice or not.
This happens pretty frequently (once a week for about 30-40 minutes), where all of a sudden my database mentions max connections when I try to connect via heidisql, and any apis calls respond with the following error:
Cannot read property 'release' of undefined
I am calling .release() after every query in mysql. Is there something I am missing, am I suppose to call .end as well? I am using nodejs with mysql.
Here is the way I wrap every query and the pool code:
var mysql = require('mysql');
var mysql_pool = mysql.createPool({
connectionLimit: config.mysql.limit,
host: config.mysql.host,
user: config.mysql.user,
password: config.mysql.pw,
database: config.mysql.db //,
// debug: true
});
var qSelect = "SELECT id FROM Users";
var qValues = [];
var qCall = mysql.format(qSelect, qValues);
mysql_pool.getConnection(function(err_pool, connection) {
if (err_pool) {
connection.release();
console.log(' Error getting mysql_pool connection: ' + err_pool);
throw err_pool;
}
connection.query(qCall, function(err, userFound, fields) {
connection.release();
if (err) {
console.log("get user : " + err);
} else {
//some code here
}
});
Can someone please advise, appreciate it.
You should remove first connection.release() used in if loop
if (err_pool) {
console.log(' Error getting mysql_pool connection: ' + err_pool);
throw err_pool;
}
Here's a working example of AWS Lambda and MySQL, but I'd like it to work with Sequelize. How do I initialize Sequelize to work with AWS Lambda? I have the authenticated IAM role working too.
https://dzone.com/articles/passwordless-database-authentication-for-aws-lambd
'use strict';
const mysql = require('mysql2');
const AWS = require('aws-sdk');
// TODO use the details of your database connection
const region = 'eu-west-1';
const dbPort = 3306;
const dbUsername = 'lambda'; // the name of the database user you created in step 2
const dbName = 'lambda_test'; // the name of the database your database user is granted access to
const dbEndpoint = 'lambdatest-cluster-1.cluster-c8o7oze6xoxs.eu-west-1.rds.amazonaws.com';
module.exports.handler = (event, context, cb) => {
var signer = new AWS.RDS.Signer();
signer.getAuthToken({ // uses the IAM role access keys to create an authentication token
region: region,
hostname: dbEndpoint,
port: dbPort,
username: dbUsername
}, function(err, token) {
if (err) {
console.log(`could not get auth token: ${err}`);
cb(err);
} else {
var connection = mysql.createConnection({
host: dbEndpoint,
port: dbPort,
user: dbUsername,
password: token,
database: dbName,
ssl: 'Amazon RDS',
authSwitchHandler: function (data, cb) { // modifies the authentication handler
if (data.pluginName === 'mysql_clear_password') { // authentication token is sent in clear text but connection uses SSL encryption
cb(null, Buffer.from(token + '\0'));
}
}
});
connection.connect();
// TODO replace with your SQL query
connection.query('SELECT * FROM lambda_test.test', function (err, results, fields) {
connection.end();
if (err) {
console.log(`could not execute query: ${err}`);
cb(err);
} else {
cb(undefined, results);
}
});
}
});
};
Instead of using mysql.createConnection() and use your RDS Signer token:
var sequelize = require('sequelize')
const Sequelize = new sequelize(
process.env.database_name,
process.env.databse_user,
token,
{
dialect: 'mysql',
dialectOptions: {
ssl: 'Amazon RDS',
authPlugins: { // authSwitchHandler is deprecated
mysql_clear_password: () => () => {
return token
}
}
},
host: process.env.db_proxy_endpoint,
port: process.env.db_port,
pool: {
min: 0, //default
max: 5, // default
idle: 3600000
},
define: {
charset: 'utf8mb4'
}
}
// then return your models (defined in separate files usually)
await Sequelize.authenticate() // this just does a SELECT 1+1 as result;
await Sequelize.sync() // DO NOT use this in production, this tries to create tables defined by your models. Consider using sequelize migrations instead of using sync()
Also it's a good idea to keep your database connection parameters in a config file so no one can see them. (process.env)
We are working with Sequelize and Lambda, but you will need to reserve more resources, in our case we need at least 1GB to run a lambda with Sequelize. Without it, just with mysql2 it runs just with 128MB.
But if you really wanna use Sequelize just replace your createConnection for something like what you will find in sequelize doc
Probably you will use the context.callbackWaitsForEmptyEventLoop=true because you may have some issues when you call the callback function and you get nothing because your Event Loop probably will never be empty.
I am using Meteor.js, Apollo/GraphQL and a MySQL database with the mysql npm package as the driver.
I am creating a connection pool as follows:
import { createPool } from 'mysql';
const pool = createPool({
host: 'localhost',
user: 'root',
password: 'asdfasdf',
database: 'soundcraft',
});
export function query(sql) {
// const connection = this;
return new Promise((resolve, reject) => {
pool.query(sql, (err, results) => {
if (err) {
reject(err);
} else {
resolve(results);
}
});
});
}
I'm not sure what's happening but after a few database requests (equal to the connection limit) it will just freeze and give no error report, and it will stay frozen until the server is restarted.
EDIT: After some reading and finding this issue it doesn't seem have anything to do with the connection being released, rather it is the fact that the connection remains open by MySQL.
It seems impractical to just increase the connection limit as eventually surely the user will still use up their quota of connections.
It doesn't look like I'm approaching this problem in the right way
I deployed a NodeJS API on Heroku and tried to connect it to a MySQL DB, so I created a connectionPool for handling connections on a ClearDB ignite account (free), which allows a maximum of 10 connections.
Every time I execute a query to the database it just adds a new connection to the stack until it reaches 10 connections and the app crashes.
My code is as follows:
connectionFactory:
var mysql = require('mysql');
function createDBConnection() {
var conn = mysql.createPool({
host: 'xxx',
user: 'xxx',
password: 'xxx',
database: 'xxx'
});
return conn;
}
module.exports = function() {
return createDBConnection;
}
And here's my select query:
function Dao(connection) {
this._connection = connection;
}
Dao.prototype.findAll = function (callback) {
this._connection.query('SELECT * FROM table',
function(errors, results) {
callback(errors,results);
});
};
module.exports = function() {
return Dao;
}
Finally here's the route I use to call it:
app.get('/products', function (req,res) {
var connection = app.persistence.connectionFactory();
var dao = new app.persistence.Dao(connection);
dao.findAll(function (err, result) {
res.format({
json: function () {
res.json(result);
}
});
});
});
I tried changing createPool() to createConnection() and then calling .end()/.destroy() function right after each query but it doesn't work at all.
Any hints?
In order to close a connection / return a connection to the pool use : connection.release()
var mysql = require('mysql');
var pool = mysql.createPool(...);
pool.getConnection(function(err, connection) {
// Use the connection
connection.query('SELECT something FROM sometable', function (error, results, fields) {
// And done with the connection.
connection.release();
// Handle error after the release.
if (error) throw error;
// Don't use the connection here, it has been returned to the pool.
});
});
mysql : Pooling connections Documentation