什么是连接池
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。
为什么要使用连接池
一次数据库的步骤
- TCP建立连接的三次握手
- MySQL认证的三次握手
- 真正的SQL执行
- MySQL的关闭
- TCP的四次握手关闭
利用连接池后

连接池优点
- 较少了网络开销
- 系统的性能会有一个实质的提升
- 没了麻烦的TIME_WAIT状态
连接池实战
预备1:模拟并发处理
由于只有并发处理才能体现连接池的价值。所以要试验连接池前我们先搞一个并发函数。
要求如下:
- 可以设置并发量
- 可以设置总执行次数
- 可以打印每次执行的耗时和总耗时
const sleep = delay => new Promise(resolve => setTimeout(resolve, delay))
const asyncFun = async (fun, curMax = 4, sum = 200) => {
let num = 0
let curNum = 0
console.time('总耗时');
console.log('beginTime:' + new Date().toLocaleString())
const result = []
while (num !== sum) {
if (curNum <= curMax) {
result.push(new Promise(async resolve => {
console.log(`Process Run 并发数:${curNum} 完成:${num}/${sum} `)
res = await fun()
curNum--
resolve(res)
}))
num++
curNum++
} else {
await sleep(10)
}
}
console.log('endTime:' + new Date().toLocaleString())
console.timeEnd('总耗时');
}
module.exports = { asyncFun }
// 测试
const test = async () => {
const delay = (Math.random() * 1000).toFixed()
await sleep(delay)
}
setTimeout(() => asyncFun(test, 4, 20))

预备2:mysql查看连接数
mysqladmin -uroot -pexample processlist

未使用连接池
(async () => {
// get the client
const mysql = require('mysql2/promise');
// 连接配置
const cfg = {
host: "localhost",
user: "root",
password: "example", // 修改为你的密码
database: "shop", // 请确保数据库存在
connectionLimit : 5,
}
// 非连接池
const query = async () => {
const connection = await mysql.createConnection(cfg)
const [rows, fields] = await connection.execute(`SELECT * FROM users`)
// console.log('select:', rows)
connection.destroy()
}
const { asyncFun } = require('./async')
await asyncFun(query, 20, 1000)
})()
执行耗时

数据库的连接数

使用连接池
下面我们改用连接池方式
// 设置连接池
const pool = await mysql.createPool(cfg)
// 连接池
const query = async () => {
const connection = await pool.getConnection()
const [rows, fields] = await connection.execute(`SELECT * FROM users`)
// console.log('select:', rows)
connection.release()
}
执行耗时

数据库的连接数

数据对比与总结
非连接池 | 连接池 | |
---|---|---|
总耗时 | 7.043 | 1.459s |
连接数 | 20(等于并发数) | 5(连接池连接数) |
在处理中只使用了五个连接有效的节省了系统资源,并且提升了性能总耗时只有原来的大约五分之一。
数据库中间件中的连接池设置
(async () => {
const Sequelize = require("sequelize");
// 建立连接
const sequelize = new Sequelize("kaikeba", "root", "example", {
host: "localhost",
dialect: "mysql",
// operatorsAliases: false,
pool: {
max: 10,
min: 0,
idle: 30000
}
});
// 定义模型
const Fruit = sequelize.define("Fruit", {
name: { type: Sequelize.STRING(20), allowNull: false },
price: { type: Sequelize.FLOAT, allowNull: false },
stock: { type: Sequelize.INTEGER, defaultValue: 0 }
});
// 同步数据库,force: true则会删除已存在表
let ret = await Fruit.sync({ force: true })
console.log('sync', ret)
ret = await Fruit.create({
name: "香蕉",
price: 3.5
})
// console.log('create', ret)
const find = async () => {
Fruit.findAll()
// console.log('findAll', JSON.stringify(ret, '', '\t'))
}
// await find()
const { asyncFun } = require('./async')
asyncFun(find,20,100)
})()