我目前正在为一个项目创建一个网络应用程序。它运行良好几个小时,然后我在我的 MySQL 数据库上遇到了“连接过多”错误。
因此,我运行
select count(host) from information_schema.processlist;
和show processlist;
发现进程列表中充满了睡眠连接,当我刷新页面时,会创建一个新连接。
这是
show processlist;
的结果
+------+-----------------+-----------------+------------+---------+--------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+------+-----------------+-----------------+------------+---------+--------+------------------------+------------------+
| 5 | event_scheduler | localhost | NULL | Daemon | 430697 | Waiting on empty queue | NULL |
| 1107 | root | localhost:53644 | test_db | Sleep | 681 | | NULL |
| 1108 | root | localhost:53817 | test_db | Sleep | 653 | | NULL |
| 1109 | root | localhost:55438 | test_db | Sleep | 392 | | NULL |
| 1110 | root | localhost:55769 | test_db | Query | 0 | init | show processlist |
| 1111 | root | localhost:50072 | test_db | Sleep | 240 | | NULL |
| 1112 | root | localhost:50075 | test_db | Sleep | 240 | | NULL |
| 1113 | root | localhost:50117 | test_db | Sleep | 234 | | NULL |
| 1114 | root | localhost:50185 | test_db | Sleep | 224 | | NULL |
| 1115 | root | localhost:50288 | test_db | Sleep | 208 | | NULL |
| 1116 | root | localhost:50331 | test_db | Sleep | 202 | | NULL |
| 1117 | root | localhost:50427 | test_db | Sleep | 188 | | NULL |
+------+-----------------+-----------------+------------+---------+--------+------------------------+------------------+
这些是我的项目代码:
// app\test\db.js
import mysql from 'mysql2/promise'
let pool
function createPool() {
try {
if (!pool) {
pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
connectionLimit: 10,
waitForConnections: true,
queueLimit: 0,
enableKeepAlive: true,
keepAliveInitialDelay: 0,
idleTimeout: 60000,
})
}
return pool
} catch (error) {
console.error(`Could not connect - ${error.message}`)
throw new Error('Database connection failed')
}
}
const db = createPool()
export async function executeQuery(sql, values = []) {
const connection = await db.getConnection()
try {
const [results] = await connection.execute(sql, values)
return results
} catch (error) {
console.error('Query execution failed:', error)
throw error
} finally {
connection.release()
}
}
export async function closePool() {
if (pool) {
await pool.end()
}
}
(以上代码由ChatGPT生成。)
// app\test\actions.js
import { executeQuery } from "./db"
export default async function testQuery() {
try {
const result = await executeQuery('SELECT 1 + 1 AS solution')
return [result[0].solution]
} catch (error) {
console.error('API error:', error)
return ["Error"]
}
}
// app\test\page.js
import testQuery from "./actions"
const res = await testQuery()
export default function DBAccess() {
return (
<div className="flex w-screen h-screen justify-center items-center">
<p className="">RESULT: {res[0]}</p>
</div>
)
}
我设法通过将
connection.release()
更改为 connection.destroy()
来“修复”它,但这违背了池的目的。我尝试过使用pool.promise()
,但这也不起作用。
所有 MySQL 服务器和所有 MariaDB 服务器都限制同时连接的数量。您可以通过以下方式检查当前值:
mysql -e 'show variables like "max_connections"'
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 2000 |
+-----------------+-------+
您可以使用以下方式更改当前值:
mysql -e 'set global max_connections = 2500'
但是该值会在数据库服务器重新启动时重置。要永久更改该值,您必须编辑
/etc/
中的配置文件,有时 /etc/my.cnf
,有时 /etc/mysql/...
(取决于操作系统)。添加到部分[mysqld]
:
[mysqld]
...
max_connections = 2500
服务器启动以来已同时使用的最大连接数和当前打开的连接数可以通过以下方式查询:
mysql -e 'show status where variable_name like "max_used_conn%" or variable_name="threads_connected"'
+---------------------------+---------------------+
| Variable_name | Value |
+---------------------------+---------------------+
| Max_used_connections | 162 |
| Max_used_connections_time | 2024-08-07 11:15:12 |
| Threads_connected | 75 |
+---------------------------+---------------------+
这个问题无法回答,因为所需的连接数量取决于很多因素。
通常,每个网站都会为每个客户端与数据库服务器建立一个连接。因此,对于第一个估计,应使用 Web 服务器(Apache、nginx 等)允许的最大客户端数量 +200。 +200 然后为后端连接提供足够的保留,例如 cron 作业使用的连接。