Skip to content

MySQL - 显示进程列表

MySQL - 使用 SHOW PROCESSLIST 进行监控

Section titled “MySQL - 使用 SHOW PROCESSLIST 进行监控”

MySQL 是一个多用户数据库系统,多个客户端可以同时连接并执行操作。每个到服务器的连接都在自己的线程中运行。SHOW PROCESSLIST 命令是一个实时诊断工具,它为你提供这些线程及其当前正在做什么的快照。

进程列表显示了当前在 MySQL 服务器内执行的线程集合。当你需要回答以下问题时,它是你的首选工具:

  • 谁连接到了我的数据库?
  • 当前正在运行哪些查询?
  • 某个查询是否卡住或运行了很长时间?
  • 为什么我收到“连接过多”错误?

要查看所有线程,你需要 PROCESS 权限。没有此权限,你只能看到自己的线程。这是一项重要的安全功能。

此命令显示有关当前进程的信息。它对于调试实时性能问题非常宝贵。

SHOW [FULL] PROCESSLIST

FULL 关键字是可选的。如果你省略它,Info 字段(包含 SQL 语句)将被截断为 100 个字符。要查看完整的查询,你必须使用 SHOW FULL PROCESSLIST。

在 MySQL 客户端中使用 \G 作为分隔符会将输出垂直格式化,这更易于阅读。

SHOW FULL PROCESSLIST\G
*************************** 1. row ***************************
Id: 8
User: app_user
Host: app-server-1.internal:48916
db: my_app
Command: Query
Time: 25
State: Sending data
Info: SELECT * FROM large_table JOIN another_table ON ... WHERE ...
*************************** 2. row ***************************
Id: 9
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: executing
Info: SHOW FULL PROCESSLIST
*************************** 3. row ***************************
Id: 10
User: app_user
Host: app-server-2.internal:51342
db: my_app
Command: Sleep
Time: 120
State:
Info: NULL

理解这些列是诊断问题的关键:

  • Id:连接标识符。你可以使用此 ID 和 KILL 命令(例如,KILL 8;)来终止一个有问题的进程。
  • User/Host:连接用户和来源主机。这有助于识别查询的来源(例如,应用程序服务器、定时任务)。
  • db:线程的默认数据库。
  • Command:线程正在执行的命令类型。Query 表示它正在主动运行一个语句。Sleep 非常常见,表示连接处于空闲状态,正在等待客户端的下一个命令。大量的 Sleep 线程可能表明应用程序连接池存在问题。
  • Time:线程处于当前状态的秒数。对于 Query 命令而言,较高的 Time 值是长时间运行查询的危险信号。
  • State:线程正在做什么的描述。这对于调试至关重要。长时间处于 Locked(锁定)、Copying to tmp table(复制到临时表)或 Creating sort index(创建排序索引)等状态表明存在性能瓶颈。
  • Info:正在执行的实际 SQL 语句(如果无则为 NULL)。始终使用 FULL 关键字来查看完整的查询。

SHOW PROCESSLIST 是一个很好的初步查看工具。对于更深入、历史性的和聚合的性能分析,现代 MySQL 版本提供了 Performance Schema(性能模式)。它是一个强大的检测引擎,以一组数据库表的形式收集性能数据。

例如,SELECT * FROM performance_schema.threads; 提供了与 SHOW PROCESSLIST 类似的信息,但以可查询的表格式呈现。Performance Schema 更复杂,但为高级调优提供了更大的洞察力。

你也可以从应用程序中执行 SHOW PROCESSLIST 来构建自定义监控仪表板或健康检查。

PHP
NodeJS
Java
Python
// 假设一个已连接的 $mysqli 对象
$sql = "SHOW FULL PROCESSLIST";
$result = $mysqli->query($sql);
if ($result) {
$processes = $result->fetch_all(MYSQLI_ASSOC);
print_r($processes);
$result->free();
}
// 假设一个来自 mysql2/promise 的已连接 'connection' 对象
async function showProcesses(connection) {
try {
const [rows] = await connection.execute('SHOW FULL PROCESSLIST');
console.log('Current Processes:', rows);
} catch (err) {
console.error('Failed to get process list:', err);
}
}
// 假设一个已连接的 'conn' 对象 (java.sql.Connection)
String sql = "SHOW FULL PROCESSLIST";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
System.out.printf("%s: %s, ", rsmd.getColumnName(i), rs.getString(i));
}
System.out.println();
}
} catch (SQLException e) {
e.printStackTrace();
}
# 假设一个来自 mysql-connector-python 的已连接 'connection' 对象和 'cursor' 对象
try:
cursor.execute("SHOW FULL PROCESSLIST")
# 使用字典游标使输出易于处理
print("Current Processes:")
for process in cursor.fetchall():
print(process)
except mysql.connector.Error as err:
print(f"Error: {err}")