DBAtlas · 数据库运维图谱

数据库变慢

症状

整个应用变慢;查询耗时远超平常,用户在抱怨。

1. 首先弄清到底是什么慢

是全部都慢,还是某个特定查询/页面慢?从什么时候开始,是否与部署/补丁/数据增长同时发生?是全系统范围还是单个数据库?这样可以将排查范围缩小到一个方向:CPU、I/O、锁或计划变更。

2. 查看活动会话和等待事件

当前正在运行什么、在等待什么?占主导地位的等待事件(I/O、锁、日志)指向瓶颈所在。

Oracle

SELECT sid, username, status, event, sql_id FROM v$session WHERE status='ACTIVE' AND type='USER';

PostgreSQL

SELECT pid, state, wait_event_type, wait_event, query FROM pg_stat_activity WHERE state='active';

MySQL

SELECT id, user, command, time, state, info FROM information_schema.processlist WHERE command<>'Sleep' ORDER BY time DESC;

SQL Server

SELECT session_id, status, wait_type, wait_time, blocking_session_id FROM sys.dm_exec_requests WHERE session_id IN (SELECT session_id FROM sys.dm_exec_sessions WHERE is_user_process = 1);

MongoDB

db.currentOp({ active: true, secs_running: { $gt: 1 } })

Redis

SLOWLOG GET 10

3. 检查阻塞

变慢最常见的原因是一个会话阻塞了其他会话。找到阻塞会话并确定阻塞链的源头。

Oracle

SELECT blocking_session, sid, seconds_in_wait, event FROM v$session WHERE blocking_session IS NOT NULL;

PostgreSQL

SELECT pid, pg_blocking_pids(pid) AS blocked_by, query FROM pg_stat_activity WHERE cardinality(pg_blocking_pids(pid))>0;

MySQL

SELECT * FROM sys.innodb_lock_waits\G

SQL Server

SELECT session_id, blocking_session_id, wait_type FROM sys.dm_exec_requests WHERE blocking_session_id<>0;

4. 找出代价最高的查询

找出资源消耗最多的前 10 个查询。通常 90% 的问题来自少数几个查询。

Oracle

SELECT sql_id, elapsed_time/1e6 sec, executions, sql_text FROM v$sql ORDER BY elapsed_time DESC FETCH FIRST 10 ROWS ONLY;

PostgreSQL

SELECT calls, total_exec_time, mean_exec_time, query FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10;

MySQL

SELECT digest_text, count_star, sum_timer_wait/1e12 sec FROM performance_schema.events_statements_summary_by_digest ORDER BY sum_timer_wait DESC LIMIT 10;

SQL Server

SELECT TOP 10 total_elapsed_time/execution_count avg_us, execution_count, SUBSTRING(t.text,1,200) FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) t ORDER BY total_elapsed_time DESC;

5. 检查可疑查询的执行计划

获取慢查询的 EXPLAIN。查找全表扫描、缺失的索引、糟糕的连接顺序或过时的统计信息。若计划突然改变,考虑收集统计信息。

Oracle

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('&sql_id', NULL, 'ALLSTATS LAST'));

PostgreSQL

EXPLAIN (ANALYZE, BUFFERS) <query>;

MySQL

EXPLAIN ANALYZE <query>;

SQL Server

SET STATISTICS PROFILE ON; <query>; SET STATISTICS PROFILE OFF;

MongoDB

db.my_collection.find({...}).explain('executionStats')  // COLLSCAN or IXSCAN?

6. 核实系统资源

在操作系统层面检查 CPU、I/O 等待(iowait)、内存和磁盘使用情况。检查缓存命中率;若偏低,可能存在内存瓶颈。问题也可能在数据库之外(磁盘已满、嘈杂邻居 VM)。

7. 决定:快速修复还是永久修复

立即缓解:终止失控查询、添加缺失的索引、收集统计信息。永久修复:重新设计查询/索引、修正内存设置、确保计划稳定(baseline/hint)。

在 DBAtlas 中打开 →