首页 > 解决方案 > MySQL 连接池如何区分 NodeJS 中的连接(使用 mysqljs)?

问题描述

我已经阅读了 mysqljs 的所有池化文档,但仍然缺少一些上下文。我的 CloudSQL 账单刚刚回来,提醒我我的旧方法存在严重缺陷。我正在寻找一些关于如何在 NodeJS 中为 CRM 处理 MySQL 池的上下文,该 CRM 会产生大量 SQL 查询。

我的旧连接方法:

//* SELECT BY ID
app.post(`/api/v1/select/id`, (req, res) => {
  let did = req.body.did;
  let host = req.body.host;
  let user = req.body.user;
  let password = req.body.password;
  let schema = req.body.schema;
  let columns = accountColumns();
  let connection = mysql.createConnection({
    host: host,
    user: user,
    password: password,
    database: schema,
    port: 3306,
  });
  if (connection.state === "disconnected") {
    connection.connect();
  }
  let selectStatement = `SELECT * FROM mydb.schema WHERE id = ${did};`;
  connection.query(selectStatement, (err, results) => {
    if (err) { throw err }
    else {
    res.send(results);
    }
  });
});

//* SELECT BY STATUS
app.post('/api/v1/status', (req, res) => {
  let status= req.body.status;
  let host = req.body.host;
  let user = req.body.user;
  let password = req.body.password;
  let schema = req.body.schema;
  let connection = mysql.createConnection({
    host: host,
    user: user,
    password: password,
    database: schema,
    port: 3306,
  });
  if (connection.state === "disconnected") {
    connection.connect();
  }
  let selectStatement= `SELECT * FROM mydb.schema WHERE status = ${status};`;
  connection.query(selectStatement, (err, results) => {
    if (err) { throw err }
      console.log(err);
    } else {
      res.json({ results });
    } 
  });
});

问题:

新方法:

实施池化,这样就不会出现与不断连接相关的荒谬开销。

//* CREATE CONNECTION
let getConnection = (host, user, password, database) => {
let pool = mysql.createPool({
    connectionLimit:10,
    host: host,
    user: user,
    password: password,
    database: database
})
  return pool
}

// Testing the initial connection
app.get('/test/:host/:user/:password/:database', (req, res) => {
  let pool = getConnection(req.params.host, req.params.user, req.params.password, req.params.database)
  pool.getConnection((err, db) => {
    if (err) { throw err }
    else {
      db.query('SELECT * FROM mydb.schema LIMIT 10;', (queryErr, records) => {
        if (queryErr) { throw queryErr }
        else {
          res.send(records)
        }
        db.release() //? do I release it if I know it will continue to be used?
      })
    }
  })
})

// This endpoint will be hit hundreds of times per session. Trying to see if the original connection will carry over without having to reconnect with the config data again
//? Would I need a try catch block here?
app.get('/test2/:host/:user/:password/:database', (req, res) => {
  let pool = getConnection(req.params.host, req.params.user, req.params.password, req.params.database)
  pool.getConnection((err, db) => {
    if (err) { throw err }
    else {
      db.query('SELECT * FROM mydb.schema LIMIT 10;', (queryErr, records) => {
        if (queryErr) { throw queryErr }
        else {
          res.send(records)
        }
        db.release() //? do I release it if I know it will continue to be used?
      })
    }
  })
})

标签: mysqlnode.jsexpressgoogle-cloud-sql

解决方案


连接池是数据库连接的缓存,可共享和重用以改善连接延迟和性能。当您的应用程序需要数据库连接时,它会临时从它的池中借用一个。当您的应用程序完成连接后,它会将连接返回到池中,下次您的应用程序需要连接到数据库时,可以重新使用该池。我建议您查看此文档以获取更多详细信息。

Cloud SQL 不会自动为您的数据库实例提供或配置负载平衡。您需要设置连接池以在多个连接点之间分配数据库的读/写请求。

如果您希望向端点发出多个请求,建议实施指数退避策略,因为它可以防止您的应用在无法连接到数据库时发送无响应数量的连接请求。但是,在您的情况下,对于 node.js,mysql 模块会自动在失败的连接尝试之间使用指数延迟。

关于数据库的不同用户访问数据的风险。我建议您查看此文档,因为它描述了 Cloud SQL 如何与 MySQL 用户一起使用。


推荐阅读