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?
Nodejs MySQL Integration: Pool Connectionsvar pool = mysql. createPool({ connectionLimit: 7, host: 'localhost', user: 'root', password: '', database: 'todoapp' });
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.
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.
var mysql = require('mysql'); var connection = mysql. createConnection({ host : 'localhost', user : 'me', password : 'secret', database : 'my_db' }); connection. connect();
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();
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:
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 Promise
s 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}`); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With