mysql - 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 });
}
});
});
问题:
- 我刚刚通过 3 周的最小测试获得了 200 美元的 GCP 云 SQL 账单
- 每次命中端点时都会打开和关闭连接(每个用户每小时可能数百次
- 它在小规模和 VPS 上工作,但这对于 GCP Cloud SQL 是不可持续的
新方法:
实施池化,这样就不会出现与不断连接相关的荒谬开销。
//* 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?
})
}
})
})
- 如果我依赖池化,用户 A 从用户 B 的数据库中获取数据是否存在风险?
- 池如何识别正在请求的连接?
- 如果当前没有开放池,是否会默认创建一个?我需要做一个 try/catch 块来确保发生这种情况吗?
- 这个语法正确吗?
- 如果“test2”端点被击中数百次,这是一种合理的处理方式吗?
解决方案
连接池是数据库连接的缓存,可共享和重用以改善连接延迟和性能。当您的应用程序需要数据库连接时,它会临时从它的池中借用一个。当您的应用程序完成连接后,它会将连接返回到池中,下次您的应用程序需要连接到数据库时,可以重新使用该池。我建议您查看此文档以获取更多详细信息。
Cloud SQL 不会自动为您的数据库实例提供或配置负载平衡。您需要设置连接池以在多个连接点之间分配数据库的读/写请求。
如果您希望向端点发出多个请求,建议实施指数退避策略,因为它可以防止您的应用在无法连接到数据库时发送无响应数量的连接请求。但是,在您的情况下,对于 node.js,mysql 模块会自动在失败的连接尝试之间使用指数延迟。
关于数据库的不同用户访问数据的风险。我建议您查看此文档,因为它描述了 Cloud SQL 如何与 MySQL 用户一起使用。
推荐阅读
- google-apps-script - 如何在 Google 表格中返回重定向的 URL
- python - OPEN-CV 错误: (-215:Assertion failed) !ssize.empty() in function 'cv::resize'
- python - 如何在 Pandas 中分组并保留所有列
- javascript - 为什么 useState 函数不是每次都初始化状态?
- logstash - 如何将日志中间的纪元时间设置为 Logstash 中的@timestamp?
- android - 性能增强失败
- c++ - 我的下堆功能有问题
- python - 使用自定义映射函数转换原始分类特征
- node.js - 使用不同的表或数据表创建多用户访问
- r - 如何在向量上使用应用?