Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

node.js + mysql connection pooling

Tags:

node.js

mysql

I'm trying to figure out how to structure my application to use MySQL most efficent way. I'm using node-mysql module. Other threads here suggested to use connection pooling so i set up a little module mysql.js

var mysql = require('mysql');  var pool  = mysql.createPool({     host     : 'localhost',     user     : 'root',     password : 'root',     database : 'guess' });  exports.pool = pool; 

Now whenever I want to query mysql I require this module and then query the databse

var mysql = require('../db/mysql').pool;  var test = function(req, res) {      mysql.getConnection(function(err, conn){          conn.query("select * from users", function(err, rows) {               res.json(rows);          })      }) } 

Is this good approach? I couldn't really find too much examples of using mysql connections besides very simple one where everything is done in main app.js script so I don't really know what the convention / best practices are.

Should I always use connection.end() after each query? What if I forget about it somewhere?

How to rewrite the exports part of my mysql module to return just a connection so I don't have to write getConnection() every time?

like image 302
kasztelan Avatar asked Aug 28 '13 19:08

kasztelan


People also ask

How do I create a MySQL connection pool in node JS?

Nodejs MySQL Integration: Pool Connectionsvar pool = mysql. createPool({ connectionLimit: 7, host: 'localhost', user: 'root', password: '', database: 'todoapp' });

What is connection pooling in node JS?

What is Connection Pooling? In a nutshell, the Connection pool is similar to a cache where we store frequently accessed data. Here the data is a database connection. The goal is to achieve the reusability of the database connections instead of creating a new connection every time there is a demand for the data.

What is MySQL connection pooling?

The MySQL Connection Pool operates on the client side to ensure that a MySQL client does not constantly connect to and disconnect from the MySQL server. It is designed to cache idle connections in the MySQL client for use by other users as they are needed.

How do I create a connection pool in MySQL?

var mysql = require('mysql'); var connection = mysql. createConnection({ host : 'localhost', user : 'me', password : 'secret', database : 'my_db' }); connection. connect();


2 Answers

It's a good approach.

If you just want to get a connection add the following code to your module where the pool is in:

var getConnection = function(callback) {     pool.getConnection(function(err, connection) {         callback(err, connection);     }); };  module.exports = getConnection; 

You still have to write getConnection every time. But you could save the connection in the module the first time you get it.

Don't forget to end the connection when you are done using it:

connection.release(); 
like image 176
Klaasvaak Avatar answered Oct 06 '22 17:10

Klaasvaak


You should avoid using pool.getConnection() if you can. If you call pool.getConnection(), you must call connection.release() when you are done using the connection. Otherwise, your application will get stuck waiting forever for connections to be returned to the pool once you hit the connection limit.

For simple queries, you can use pool.query(). This shorthand will automatically call connection.release() for you—even in error conditions.

function doSomething(cb) {   pool.query('SELECT 2*2 "value"', (ex, rows) => {     if (ex) {       cb(ex);     } else {       cb(null, rows[0].value);     }   }); } 

However, in some cases you must use pool.getConnection(). These cases include:

  • Making multiple queries within a transaction.
  • Sharing data objects such as temporary tables between subsequent queries.

If you must use pool.getConnection(), ensure you call connection.release() using a pattern similar to below:

function doSomething(cb) {   pool.getConnection((ex, connection) => {     if (ex) {       cb(ex);     } else {       // Ensure that any call to cb releases the connection       // by wrapping it.       cb = (cb => {         return function () {           connection.release();           cb.apply(this, arguments);         };       })(cb);       connection.beginTransaction(ex => {         if (ex) {           cb(ex);         } else {           connection.query('INSERT INTO table1 ("value") VALUES (\'my value\');', ex => {             if (ex) {               cb(ex);             } else {               connection.query('INSERT INTO table2 ("value") VALUES (\'my other value\')', ex => {                 if (ex) {                   cb(ex);                 } else {                   connection.commit(ex => {                     cb(ex);                   });                 }               });             }           });         }       });     }   }); } 

I personally prefer to use Promises and the useAsync() pattern. This pattern combined with async/await makes it a lot harder to accidentally forget to release() the connection because it turns your lexical scoping into an automatic call to .release():

async function usePooledConnectionAsync(actionAsync) {   const connection = await new Promise((resolve, reject) => {     pool.getConnection((ex, connection) => {       if (ex) {         reject(ex);       } else {         resolve(connection);       }     });   });   try {     return await actionAsync(connection);   } finally {     connection.release();   } }  async function doSomethingElse() {   // Usage example:   const result = await usePooledConnectionAsync(async connection => {     const rows = await new Promise((resolve, reject) => {       connection.query('SELECT 2*4 "value"', (ex, rows) => {         if (ex) {           reject(ex);         } else {           resolve(rows);         }       });     });     return rows[0].value;   });   console.log(`result=${result}`); } 
like image 23
binki Avatar answered Oct 06 '22 18:10

binki