NodeJS + ExpressJS 管理 mysql DB 连接的正确方法

dev*_*mat 3 mysql mariadb node.js express reactjs

我正在使用 ReactJS / NodeJS + ExpressJS 开发一个应用程序。

我试图了解处理数据库连接的最佳方法是什么。这段代码有效,但似乎它不断增加连接数,我认为这不好但你可能会启发我这一点。

当我刚启动 mysql 服务器(没有运行我的应用程序)时,连接数已经是 60,这些是什么?

MariaDB [(none)]> show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 60    |
+-----------------------------------+-------+
7 rows in set (0.001 sec)
Run Code Online (Sandbox Code Playgroud)

然后,一旦我运行我的应用程序,连接数就会增加到 64:

MariaDB [(none)]> show status like 'Conn%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Connection_errors_accept          | 0     |
| Connection_errors_internal        | 0     |
| Connection_errors_max_connections | 0     |
| Connection_errors_peer_address    | 0     |
| Connection_errors_select          | 0     |
| Connection_errors_tcpwrap         | 0     |
| Connections                       | 64    |
+-----------------------------------+-------+
7 rows in set (0.000 sec)
Run Code Online (Sandbox Code Playgroud)

然后,每次我重新启动后端应用程序或从前端发出请求时,连接数似乎都会增加。

我不确定如何管理连接,并且我承认我正在使用的代码的某些部分对我来说并不是很清楚(我是反应、表达和节点的新手),所以请耐心等待。

这是我正在使用的代码的一部分,希望您能帮助我找到管理连接的最佳方法。

由于connection将在我的应用程序的多个区域中使用,我创建了一个包含以下内容的 .js 文件:

class Connection {

    static connect() {

        var mysql = require('mysql');
        var connection = null;

        var connection_settings = {
            host     : 'localhost',
            database : '..',
            user     : '..',
            password : '..',
        }

        connection = mysql.createConnection(connection_settings);

        connection.connect(function(err) {
            if(err) {
                console.log('error when connecting to db:', err);
            } 
        });

        return connection;

    }

}

module.exports = { Connection }
Run Code Online (Sandbox Code Playgroud)

然后是包含查询数据库的代码的文件:

const { Connection } = require('../database.js')

function openLessonSections (lessonID, connection){

    return new Promise(function (resolve, reject){
        const sql = "SELECT * FROM sections WHERE lesson_id=" + lessonID;
        connection.query (sql, function (error, result){
            console.log('Loading lesson "' + lessonID + '".');
            if (error) reject (error);
            resolve (result);
        });
    });
}

async function openLesson(lessonID, connection){
    return await openLessonSections(lessonID, connection);
}

exports.lessonOpen = function(req, res, next) {

    const connection = Connection.connect();

    console.log('request received');

    const lessonID = JSON.parse(req.body.lessonID);

    console.log('Opening lesson: ' + lessonID);

    openLesson(lessonID, connection)
        .then(function(result){
            console.log('The lesson was opened successfully.');
            res.status(200).json({sections: result});
        })
        .catch(function (error){
            res.status(500).json(error);
            console.log('There was an error while opening the lesson. ' + error);
        });

    connection.end();

}
Run Code Online (Sandbox Code Playgroud)

我知道我做错了,而且我对最好的方法有点困惑。

Dan*_*Dan 5

一种选择是创建连接池(一次):

const mysql = require('mysql');
const pool = mysql.createPool({
  host: 'myhost',
  user: 'myuser',
  password: 'mypass',
  database: 'mydb',
  connectionLimit: 10,
  supportBigNumbers: true
})
Run Code Online (Sandbox Code Playgroud)

然后每当有查询时,它就会从池中获取连接:

function query(sql, args) {
  return new Promise((resolve, reject) => {
    pool.getConnection(function(err, connection) {
      if (err) {
        return reject(err);
      }
      connection.query(sql, args, function(err, result) {
        connection.release();
        if (err) {
          return reject(err);
        }
        return resolve(result);
      });
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

注意:此示例已包含在 Promise 样式代码(而不是回调样式代码)的 Promise 中。

导出query函数:

module.exports = {
  query
};
Run Code Online (Sandbox Code Playgroud)

将上述所有代码放在一个模块中,例如db.js,并按如下方式使用它:

const mysql = require('mysql');
const pool = mysql.createPool({
  host: 'myhost',
  user: 'myuser',
  password: 'mypass',
  database: 'mydb',
  connectionLimit: 10,
  supportBigNumbers: true
})
Run Code Online (Sandbox Code Playgroud)