我已经阅读了mysqljs中的所有池文档,但仍然缺少一些上下文。我的CloudSQL账单刚刚回来,提醒我我的旧方法存在严重缺陷。我正在寻找一些关于如何在NodeJS中处理MySQL池的上下文,用于进行大量SQL查询的CRM。
我的旧连接方法:
//* 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模块会在失败的连接尝试之间自动使用指数延迟。
关于,您数据库的不同用户访问数据的风险。我建议你看一下这个文档,因为它描述了云SQL如何与MySQL用户一起工作。