❤Node-数据库高并发createPool
1、 mysql模块的认识
Node.js使用mysql模块与数据库交互的两种主要的连接方式:createPool和createConnection。
在Node.js中,mysql模块通常用于与MySQL数据库进行交互。mysql模块提供了两种主要的连接方式:createPool和createConnection。它们之间的主要区别在于连接的管理方式和性能方面。
(1) createPool:
createPool方法创建了一个连接池,连接池会在需要时创建多个连接,并在不需要时将连接放回池中,以便重复使用。这种方式适用于大量并发请求的情况,因为它可以有效地管理连接,避免了频繁地创建和销毁连接的开销。- 连接池的大小通常可以配置,以控制同时打开的连接数量,以防止数据库过载。这样可以确保在高负载时系统仍然能够保持稳定。
- 使用连接池时,通过从池中获取连接来执行查询操作,执行完毕后将连接释放回池中,这样可以最大程度地重用连接,提高性能和效率。
示例代码:
js
const mysql = require('mysql');
const pool = mysql.createPool({
connectionLimit: 10, // 最大连接数
host: 'localhost',
user: 'root',
password: 'password',
database: 'my_database'
});
pool.getConnection((err, connection) => {
if (err) throw err;
connection.query('SELECT * FROM my_table', (error, results, fields) => {
connection.release(); // 释放连接
if (error) throw error;
console.log(results);
});
});
(2) createConnection:
js
- `createConnection` 方法每次调用都会创建一个新的数据库连接。这种方式适用于低负载的场景或者在单个请求中只需要少量查询的情况。
- 每次调用`createConnection`都会创建一个新的连接,执行完毕后需要手动关闭连接,否则会造成资源浪费和内存泄漏。
示例代码:
js
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'my_database'
});
connection.connect((err) => {
if (err) throw err;
console.log('Connected to MySQL database');
connection.query('SELECT * FROM my_table', (error, results, fields) => {
if (error) throw error;
console.log(results);
connection.end(); // 关闭连接
});
});
总的来说,createPool适用于高并发的情况,可以有效地管理连接,提高性能和可靠性,而createConnection适用于低负载的场景或者简单的应用中。
2、数据库高并发createPool方式
之前我们采用的都是这种createConnection方式,上一章节我们讲了createConnection和createPool的区别和联系,接下来我们也采用createPool这种更加高效的方式,接下来我们就使用这种方式优化我们的数据库接口。
之前我们连接数据库采用的这种方式:
// 创建数据库链接(非高并发的方式)
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost', // 数据库主机地址,如果是本地数据库则使用localhost
user: 'root', // 数据库用户名
password: 'xxxxx', // 数据库密码
database: 'nexus', // 要连接的数据库名
});
module.exports = connection;
现在我们更改为高并发createPool方式,总得来说只需要把connection更改为createPool方式即可
(1)查询方式更改为createPool方式
js
app.get('/api/user', (req, res) => {
const { name, age,sex } = req.query;
const values =[name, age,sex];
let query = 'SELECT * FROM user';
// 构建查询条件
const params = [];
if (name !== undefined&&name !== ''&&name !== null) {
query += ' WHERE name = ?';
params.push(name);
}
if (age !== undefined&&age !== ''&&age !== null) {
query += params.length ? ' AND' : ' WHERE';
query += ' age = ?';
params.push(age);
}
// 查询数据库并返回数据
connectionpool.query(query,params,(err, results) => {
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}
res.json({
code:'200',
data:results,
});
});
});
(2)新增用户post方法更改为我们的连接池方式
js
// 新增用户 POST 请求处理程序
app.post('/api/user', (req, res) => {
const { name, age } = req.body; // 从请求体中获取数据
const values = [name, age];
const insertSql = `INSERT INTO user (name, age) VALUES (?, ?)`;
connectionpool.query(insertSql, values, (err, results) => {
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}
res.json({
code:'200',
data:results,
});
});
});
(3)获取用户详情
js
// 获取用户详情 3
app.get('/api/user/:id', (req, res) => {
const { id } = req.params;
const values =[id];
let query = 'SELECT * FROM user WHERE id = ?';
connectionpool.query(query,values,(err, results) => {
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}
res.json({
code:'200',
data:results?results[0]:{},
});
});
});
(4)put修改方法的更改
js
js
app.put('/api/user', (req, res) => {
// console.log(req.body);
const { name, age ,id} = req.body; // 从请求体中获取数据
const values = [name, age, id];
// 准备 SQL 插入语句
const sql = "UPDATE user SET name = ?, age = ? WHERE id = ?";
connectionpool.query(sql, values, (err, results) => {
// console.log(err,'err');
// console.log(results,'results');
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}
res.json({
code:'200',
data:results,
});
});
});
(5)删除用户delete方法的更改
js
// 删除用户数据 DELETE请求处理程序
app.delete('/api/user/:id', (req, res) => {
// const {id} = req.body; // 从请求体中获取数据
const id = req.params.id;
// console.log(id,'id');
const values = [id];
const sql = "DELETE FROM user WHERE id = ?";
connectionpool.query(sql, values, (err, results) => {
// console.log(err,'err');
// console.log(results,'results');
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}
res.json({
code:'200',
data:results,
});
});
});
最后测试一下我们的增删改查以及我们的查询条件,没问题。高并发createPool方式更改ok!
(6)优化多进程
优化一下,接口里面允许同一个时间查询多个接口
js
multipleStatements: true, // 允许执行多条语句
// 创建数据库连接池 createPool(高并发方式)
const connectionpool = mysql.createPool({
host: 'localhost', // 数据库主机地址,如果是本地数据库则使用localhost
user: 'root', // 数据库用户名
password: '', // 数据库密码
database: '' // 要连接的数据库名
multipleStatements: true, // 允许执行多条语句
});
❤Node-分页查询
1、优化分页查询接口
之前我们的接口并没有进行分页的参数设置,在大批量的数据之中一般我们为了性能以及用户的体验,一般还是需要对于表格数据进行分页和优化。因此我们查询接口的分页是十分有必要的,接下来我们就优化一下我们分页查询的方式:
分页参数设置(前端的参数)
分页参数有两个,一个是当前页的页数,另一个是当前页有多少条。
js
pageNum: 1 //页码数(也就是当前是多少页)
pageSize:10 //页条数(也就是当前页是多少条)
我们可以先打印出来看看我们查询蚕食,这边我们可以看到前台传过来的查询参数里面加了 pageNum: '1', pageSize: '10' }的参数,我们把这个参数打印如下图:
console.log(req.query,'req.query');
{ name: '', age: '', pageNum: '1', pageSize: '10' } req.query
查询条件 SELECT * FROM user LIMIT ?, ? [ 0, 10 ]
{ name: '', age: '', pageNum: '1', pageSize: '10' } req.query
查询条件 SELECT * FROM user LIMIT ?, ? [ 0, 10 ]
{ name: '', age: '', pageNum: '1', pageSize: '10' } req.query
查询条件 SELECT * FROM user LIMIT ?, ? [ 0, 10 ]
先看看我们的数据库查询语句是否正确
js
SELECT * FROM user WHERE age = 18 LIMIT 0, 10
2、拼接上我们的参数
当我们pageNum:1 pageSize10 的时候返回数据如图
js
{
"total": 10,
"code": 200,
"data": [
{
"id": 1,
"name": "管理员",
"age": "1888",
"sex": 1,
"address": "地址",
"state": 1,
},
{
"id": 2,
"name": "后台开发人员",
"age": "18",
"sex": 2,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
{
"id": 3,
"name": "教师",
"age": "18",
"sex": 2,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
{
"id": 4,
"name": "普通人员",
"age": "20",
"sex": 1,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
{
"id": 7,
"name": "张三",
"age": "18",
"sex": 1,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
{
"id": 12,
"name": "可爱",
"age": "18",
"sex": 2,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
{
"id": 20,
"name": "san娟",
"age": "20",
"sex": 1,
"createtime": null,
"address": null,
"state": 2,
"phone": null,
"username": null,
},
{
"id": 21,
"name": "乐乐",
"age": "8",
"sex": 1,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
{
"id": 38,
"name": "lin",
"age": "19",
"sex": null,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
{
"id": 39,
"name": "童年的自己",
"age": "80",
"sex": null,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
}
]
}
修改查询的分页为2,这个时候发现页码已经更改为2 了,查询无误
js
{
"total": 10,
"code": 200,
"data": [
{
"id": 1,
"name": "管理员",
"age": "1888",
"sex": 1,
"address": "地址",
"state": 1,
},
{
"id": 2,
"name": "后台开发人员",
"age": "18",
"sex": 2,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
}
]
}
3、offset偏移量参数
这里需要注意的就是这个offset参数 offset是偏移量,通过计算偏移量 (pageNum - 1) * pageSize 来动态生成偏移量,然后将 age、name、偏移量和每页的行数作为参数传递给 SQL 查询的 LIMIT 子句和 WHERE 子句。
我们将查询语句放进去尽心查询,这个时候报错了,查询语句如下:
js
if (pageNum !== undefined&&pageSize !== ''&&pageSize !== null) {
query += params.length ? ' AND' : ' WHERE';
query += ' LIMIT ?, ?';
let offset = (pageNum - 1) * pageSize;
params.push(offset);
params.push(parseInt(pageSize));
}
查询语句之中我们多加了' AND' : ' WHERE',排查修改以后我们更改我们的分页查询方式:
js
const { name, age,sex,pageNum,pageSize } = req.query;
if (pageNum !== undefined&&pageSize !== ''&&pageSize !== null) {
query += ' LIMIT ?, ?';
let offset = (pageNum - 1) * pageSize;
params.push(offset);
params.push(10);
}
查询无误!
这个时候我将pageSize也给添加的时候发现错误
这个时候一直报错提示我You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''10'' at line 1", sqlState: '42000', index: 0, sql: "SELECT * FROM user LIMIT 0, '10'" }
大致意思就是因为我的数据类型为字符串,转化方式有以下三种,我选择了parseInt 方式
js
parseInt
parseFloat
Number
- 需要注意的是查询方式,这里需要使用
O,10的限制页码条数:
js
code: 'ER_PARSE_ERROR',
errno: 1064,
sqlMessage: "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '10' at line 1",
sqlState: '42000',
index: 0,
sql: "SELECT * FROM user LIMIT O,'10'"
ok更改以后查询无误!
js
{ name: '', age: '', pageNum: '1', pageSize: '10' } req.query
查询条件 SELECT * FROM user LIMIT ?, ? [ 0, 10 ]
{ name: '', age: '', pageNum: '1', pageSize: '10' } req.query
查询条件 SELECT * FROM user LIMIT ?, ? [ 0, 10 ]
{ name: '', age: '', pageNum: '1', pageSize: '10' } req.query
查询条件 SELECT * FROM user LIMIT ?, ? [ 0, 10 ]
4、返回总条数total
先试试我们的Sql查询语句
js
SELECT COUNT(*) AS total FROM user;
查询效果如下

接下来我们把这个查询加到我们的查询条件里面去
js
connectionpool.query(query,params,(err, results) => {
// console.log(err,'err');
// console.log(results,'results');
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}else{
let sqltotal = `SELECT COUNT(*) AS total FROM user;`
// 查询数据库并返回数据
connectionpool.query(sqltotal,(errtotal, total) => {
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}else{
res.json({
total,
code:'200',
data:results,
});
}
});
}
});
查询以后可以看出我们的查询结果如下,这里的返回结果条数是嵌套在数组里面。
js
{
"total": [{"total": 12}],
"code": 200,
"data": [
{
"id": 1,
"name": "管理员",
"age": "1888",
"sex": 1,
"address": "地址",
"state": 1,
},
...
]
}
优化一下我们的查询方式
js
connectionpool.query(sqltotal,(errtotal, rows) => {
let total = rows[0]['total'];
if (err) {
console.error('Error querying database:', err);
res.status(500).json({ error: 'Internal server error' });
return;
}else{
res.json({
total:total,
code:'200',
data:results,
});
}
});
查询成功!
js
{
"total": 12,
"code": 200,
"data": [
{
"id": 1,
"name": "管理员",
"age": "1888",
"sex": 1,
"address": "地址",
"state": 1,
},
{
"id": 2,
"name": "后台开发人员",
"age": "18",
"sex": 2,
"createtime": null,
"address": null,
"state": 1,
"phone": null,
"username": null,
},
...
]
}


2611

被折叠的 条评论
为什么被折叠?



