nodejs mysql module errors - mysql

I have a nodejs module which get result from a mysql database and insert into another mysql database within a given interval. After few queries it just get stuck and throw "ER_CON_COUNT_ERROR" and says Too many connections. My module is as follows:
function get_data() {
const mysql = require('mysql');
const moment = require('moment');
var items_per_query = 1000;
let to_connection = mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'pass',
database: 'todatabase'
});
let from_connection = mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'pass',
database: 'fromdatabase'
});
from_connection.query("SELECT p.*, d.uniqueid as imei FROM tc_positions p left join tc_devices d on d.id = p.deviceid order by p.id desc limit " + items_per_query, function (err, result, fields) {
if (err) throw err;
var items = [];
var table_columns_list = {};
if (Object.keys(result).length > 0) {
Object.keys(result).forEach(function (key) {
var x = result[key];
table_columns_list = {
'dt_server': moment(x['servertime']).format('YYYY-MM-DD HH:MM:ss'),
'dt_tracker': moment(x['devicetime']).format('YYYY-MM-DD HH:MM:ss'),
'lat': x['latitude'],
'long': x['longitude'],
'altitude': x['altitude'],
'angle': x['course'],
'speed': x['speed'],
'params': x['attributes'],
'fix_time': moment(x['fixtime']).format('YYYY-MM-DD HH:MM:ss'),
'accuracy': x['accuracy'],
'network': x['network']
}
items.push({ 'id': x['id'], 'table_name': 'table_' + x['imei'], 'table_columns': table_columns_list });
});
}
if (items.length >=500) {
var items_to_be_removed = [];
var total_rows_inserted = 0;
for (var x = 0; x < items.length; x++) {
to_connection.query(imei_insert, function (err, results, fields) {
if (err) {
console.log(err.message);
}
else {
let createTable = " create table if not exists .... ";
to_connection.query(createTable, function (err, results, fields) {
if (err) {
console.log(err.message);
}
else {
let insert_data = "INSERT INTO .... ";
to_connection.query(insert_data, function (err, results, fields) {
if (err) {
console.log(err.message);
}
total_rows_inserted++;
items_to_be_removed.push(row_id);
if (total_rows_inserted == items.length) {
//remove data from traccar positions table that were inserted to platform
var ids = items_to_be_removed.join(",");
from_connection.query("DELETE FROM tc_positions where id IN(" + ids + ")", function (err, results, fields) {
if (err) throw err;
console.log('removed ' + total_rows_inserted + ' rows from traccar');
return get_data(); // after finish all task call the same function again
});
}
});
}
});
}
});
}
}
else {
setInterval(get_data, 15000);
}
});
}
and I just call get_data(); function to run. Is there any efficient way to run this module smoothly. I should run it 7 days 24 hours without any interruption.

You're creating a new connection to the servers each time get_data() runs, which is overwhelming them. You need to reuse connections, as for example with connection pooling.

Related

How to make return wait for MySQL connection to end? Node.js

I'm new to Node.js I'm testing some code on Wix to check my database if a account name already exists prior to allowing a new one to be created (I'm purposely not using the WHERE tag at the moment for learning purposes).
Currently the method check account name returns before the connection finishes, not allowing the check to take place properly.
Any help appreciated.
export function tryToCreateAccount(login, password)
{
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'host',
user: 'user',
password: 'pass',
database: 'db'
});
if(checkAccountName(login, connection))
{
console.log("Name didn't exist.");
}
else
{
console.log("Name Existed.");
}
}
function checkAccountName(account_name, connection)
{
var accountNameAvailable = true;
connection.connect(function (err)
{
if(err) throw err;
connection.query("SELECT login FROM accounts", function (err, result)
{
if (err) throw err;
for(var i = 0; i < result.length ; i++)
{
if(result[i].login == account_name)
{
console.log("Should of been false");
connection.end;
accountNameAvailable = false;
}
}
});
connection.end;
});
return accountNameAvailable;
}
I figured out why it wasn't doing anything, the next was getting called too late since the connection ended and next was within the connection code block.
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'host',
user: 'user',
password: 'pass',
database: 'db'
});
export function tryToCreateAccount(login, password)
{
checkAccountName(login, connection, function(err, accountNameAvailable)
{
if(err || !accountNameAvailable){
console.log("Name didn't exist.");
}
else
{
console.log("Name Existed.");
}
})
}
function checkAccountName(login, connection, next)
{
var accountNameAvailable = false;
connection.connect(function (err)
{
if(err) next(err);
connection.query("SELECT login FROM accounts", function (err, result){
if (err) next(err);
for(var i = 0; i < result.length ; i++)
{
if(result[i].login == login)
{
accountNameAvailable = true;
}
}
next(null, accountNameAvailable);
connection.end();
});
});
}
Welcome to Node.js (and the world of Async functions (and Promises (and Callbacks)))
I've written this in the "callback" style, but I highly recommend looking into async/await for something like this, as well as understanding how "promises" fit into the picture.
// to test, call tryToCreateAccount('login','pass',function(err,data){console.log(err,data)});
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'host',
user: 'user',
password: 'pass',
database: 'db'
});
export function tryToCreateAccount(login, password, next)
{
checkAccountName(login, connection, function(err, accountNameAvailable){
if(err || !accountNameAvailable){
console.log("Name didn't exist.");
next(err || 'Name didn't exist.')
}
else
{
console.log("Name Existed.");
next(null, true)
}
})
}
function checkAccountName(account_name, connection, next)
{
var accountNameAvailable = false;
connection.connect(function (err)
{
if(err) next(err);
connection.query("SELECT login FROM accounts", function (err, result){
if (err) next(err);
for(var i = 0; i < result.length ; i++)
{
if(result[i].login == account_name)
{
console.log("Should of been false");
connection.end;
accountNameAvailable = true;
}
}
connection.end();
next(null, accountNameAvailable);
});
});
}

How to insert into a SQL table using a for-loop in NodeJS?

I am having trouble finding the proper SQL syntax on adding items to my table using a for loops and an array. This is what I am trying to do:
var mysql = require('mysql');
var con = mysql.createConnection({
host: "localhost",
user: "root",
database: 'DUSAgeocodeDB'
});
var addreses = ['addres1', 'address2', 'address3'];
var latitude = [12, 45, 789];
var longitude = [987, 654, 321];
for (var i =0; i <addreses.length; i++) {
con.connect(function(err) {
con.query(`INSERT INTO maintable (mainaddress, latitude, longitude) VALUES (${addreses[i]}, ${latitude[i]}, ${longitude[i]} )`, function (err, result) {
if(err) throw err;
console.log('VALUES ADDED')
});
})
}
What would be the proper syntax on the con.query() statement in order to save those values to mysql table? This is something else that I've tried but it does not work
for (var i =0; i <addreses.length; i++) {
con.connect(function(err) {
con.query("INSERT INTO maintable (mainaddress, latitude, longitude) VALUES ("+${mysql.escape(addreses[i])}+", "+${mysql.escape(latitude[i])}+", "+${mysql.escape(longitude[i])}" )", function (err, result) {
if(err) throw err;
console.log('VALUES ADDED')
});
})
}
I would suggest leveraging Promise.all this way you can fire multiple async operations off in parallel. mysql does not come with promise support, however, you could use msql2 that does. Here I have wrapped the existing con.query in its own promise.
function queryPromise(query) {
return new Promise((resolve, reject) => {
con.query(query, (err, result) => {
if (err) {
return reject(err);
}
return resolve(result);
});
});
}
con.connect(async (err) => {
await Promise.all(
addreses.map((_, i) => {
return queryPromise(
`INSERT INTO maintable (mainaddress, latitude, longitude) VALUES (${addreses[i]}, ${latitude[i]}, ${longitude[i]} )`
);
})
);
});
you could write
var mysql = require('mysql');
var con = mysql.createConnection({
host: "localhost",
user: "root",
database: 'DUSAgeocodeDB'
});
var addreses = ['addres1', 'address2', 'address3'];
var latitude = [12, 45, 789];
var longitude = [987, 654, 321];
con.connect(function(err) { // create a single connection to execute all the queries
for (let i=0; i < addreses.length; i++) { //use let instead of var to prevent issues with closures in asynchronous code
con.query(`INSERT INTO maintable (mainaddress, latitude, longitude) VALUES (${addreses[i]}, ${latitude[i]}, ${longitude[i]} )`, function (err, result) {
if(err) throw err;
console.log('VALUES ADDED')
});
})
}

Function won't return an array of items created from MySQL Query (async/Await)

I'm trying to create an array of items from a MySQL query to return from an async function but the returns are empty.
Things I've tried:
Read up to the latest info about async/await
Stack overflow
Numerous test around changing code, replacing return calls, rewriting functions.
This is for a new webservice (nodejs) that needs to initialize values from a MySQL database and after that fast access to the values to compare them against values pulled from the internet. To limit the amount of database calls I'm planning to have the values in an array (in-memory) and whenever they change enough (based on calculations) write them to the DB.
All is Linux based using Node 11
require('dotenv').config()
var mysql = require('mysql')
var dbconnection = mysql.createConnection({
host: 'localhost',
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PW,
database: process.env.MYSQL_DB
})
dbconnection.connect(function (err) {
if (err) {
console.error('error connecting: ' + err.stack)
}
})
async function ReadDB () {
var ArrBuyPrice = []
var query = 'SELECT * FROM pricing'
var items = await dbconnection.query(query, function (err, rows, result) {
if (err) throw err
for (var i in rows) {
ArrBuyPrice.push(rows[i].price_buy.toFixed(8))
}
return ArrBuyPrice
})
return items
}
async function InitialProcess () {
var DbResult = await ReadDB()
console.log(DbResult)
}
InitialProcess()
I would expect the console.log output to be [ '0.00000925', '0.00000012' ]
// https://stackoverflow.com/questions/44004418
var mysql = require('mysql')
var dbconnection = mysql.createConnection({
host: 'localhost',
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PW,
database: process.env.MYSQL_DB
})
const util = require('util');
async function ReadDB() {
var ArrBuyPrice = []
const query = util.promisify(dbconnection.query).bind(dbconnection);
try {
const rows = await query('select * from pricing');
for (var i in rows) {
ArrBuyPrice.push(rows[i].price_buy.toFixed(8))
}
return ArrBuyPrice;
} catch (error) {
console.log(error)
return [];
} finally {
dbconnection.end();
}
}
async function InitialProcess() {
var DbResult = await ReadDB()
console.log(DbResult)
}
InitialProcess();
What is Problem:
async function ReadDB() {
var ArrBuyPrice = []
var query = 'SELECT * FROM pricing';
var items = await dbconnection.query(query, function (err, rows, result) {
if (err) throw err
for (var i in rows) {
ArrBuyPrice.push(rows[i].price_buy.toFixed(8))
}
return ArrBuyPrice
});
return items
}
At await dbconnection.query, await is not working, and it is unnecessary, because dbconnection.query() function is not Promise function.
So, the rows which query result will arrive after return items;
And return ArrBuyPrice function is not running.

Node.js synchronously with mysql query

I am trying to implement a synchronous query in mysql with node.js, I tried several ways and did not succeed
I am new to node.js
I use express.js
connection.js
var mysql = require('mysql');
var connMySql = function() {
return mysql.createConnection({
host : 'localhost',
user : 'root',
password : '******',
database : 'ress'
});
}
module.exports = function() {
return connMySql;
}
DAO.js
function UserDAO(connection){
this._connection = connection();
}
UserDAO.prototype.createUser = function (user, callback){
var sql = "insert into... ";
this._connection.query(sql, function(err, result){
//console.log(result)
//console.log()
if (err){
callback(err,false )
}
if (result){
var newI = result.insertId
var sqlOther = "insert into ..... ";
this._connection.query(sql, function(err, result){
if (err){
callback(err,false )
}else if (result.length > 0){
callback(false, result.insertId)
}
});
}
});
}
I try implements await, async and Promisse(.then) but no success.
What I need to make calls synchronously and return insert id?
thanks
From mysql repo I see that you're missing connection.connect()
connection.js
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '******',
database : 'ress'
});
connection.connect(function(err) {
if (err) throw err;
});
module.exports = connection;
DAO _connection must be closed when it's done with it's job
UserDAO.prototype.createUser = function (user, callback){
var sql = "insert into... ";
this._connection.query(sql, function(err, result){
//console.log(result)
//console.log()
if (err){
callback(err,false )
this._connection.end();
}
if (result){
var newI = result.insertId
var sqlOther = "insert into ..... ";
this._connection.query(sql, function(err, result){
if (err){
callback(err,false )
} else if (result.length > 0){
callback(false, result.insertId)
}
this._connection.end();
});
}
});
}

Add every item of an Array to mysql db

I'm pretty new to Java Script and tried to write a small programm to add users to a database. My problem is, that my programs doesn't add every user ones. It adds the last user as often as there are users in the list. users has more than 2 Objects and all the Objects have all field filled.
for(i = 0; i<users.length; i++)
{
var user = users[i];
console.log(user.lastonline)
pool.getConnection(function(err, connection) {
if (err) throw err;
var quer = connection.query('INSERT INTO users SET `steamid` = '+ connection.escape(user.steamid)+', `name`='+connection.escape(user.name)+', `lastonline`='+connection.escape(user.lastonline)+' ON DUPLICATE KEY UPDATE `name`='+connection.escape(user.name)+', `lastonline`='+connection.escape(user.lastonline)+'', function(err, result) {
connection.release();
});
console.log(quer.sql);
});
}
I tried to rewrite this in a lot of different way, but most time I get something like this:
TypeError: Cannot read property 'steamid' of undefined
for(i = 0; i<users.length; i++)
{
pool.getConnection(function(err, connection) {
console.log(users[i]["steamid"]);
if (err) throw err;
var quer = connection.query('INSERT INTO users SET `steamid` = '+ connection.escape(users[i]["steamid"])+', `name`='+connection.escape(users[i].name)+', `lastonline`='+connection.escape(users[i].lastonline)+' ON DUPLICATE KEY UPDATE `name`='+connection.escape(users[i].name)+', `lastonline`='+connection.escape(users[i].lastonline)+'', function(err, result) {
connection.release();
});
console.log(quer.sql);
});
}
EDIT:
Rest of the programm
var mysql = require('mysql');
var Promise = require("bluebird");
var pool = mysql.createPool({
connectionLimit : 10,
host : 'localhost',
user : 'zar',
password : 'qxLLPa06iEs2Bzsu',
database : 'zar',
socketPath: '/var/run/mysqld/mysqld.sock'
});
pool.on('connection', function (connection) {
console.log("connection made")
});
//my testing users
var users = [];
times = Date.now();
user1 = {steamid:012345678912345658,name:"user1",lastonline:times};
user2 = {steamid:012345678912345628,name:"user2",lastonline:times};
user3 = {steamid:012345678912345618,name:"user3",lastonline:times};
users.push(user1);
users.push(user2);
users.push(user3);
Edit: Fixed to use only one connection.
Previous version was getting a new connection for every user.
You should use Promises:
pool.getConnection((err, connection) => {
if (err) {
console.log(err);
return;
}
var tasks = users.map((user) => {
return new Promise((resolve, reject) => {
if (err) {
return reject(err);
}
var quer = connection.query('INSERT INTO users SET `steamid` = ' + connection.escape(user.steamid) + ', `name`=' + connection.escape(user.name) + ', `lastonline`=' + connection.escape(user.lastonline) + ' ON DUPLICATE KEY UPDATE `name`=' + connection.escape(users.name) + ', `lastonline`=' + connection.escape(users.lastonline) + '', function (err, result) {
if (err) {
return reject(err);
}
resolve(result);
});
});
});
Promise.all(tasks)
.then((results) => {
// Array of results passed in resolve
connection.release();
})
.catch((err) => {
// All errors you reject are catched here
});
});
This should workd but still, you are executing all queries in parallel, which can be pretty aggressive for the DB.
I suggest you to look into bluebird Promise.each for better results.