本文档用于针对基于MogDB数据库系统生产环境下,SQL运行缓慢,系统性能负载压力过大等问题进行问题定位,问题处理流程,问题成因等各个方面提供指导。 适用于MogDB DBA及相关技术人员。
1、前台业务运行缓慢; 2、前台业务运行SQL,但是无返回结果; 3、数据库所在服务器负载高; 4、数据库运行SQL查询没有响应; 5、单条SQL运行长时间没有返回结果。
确定是否存在系统资源瓶颈(CPU,Disk IO,MEM),并通过瓶颈类型,简单推测可能出现的问题
## CPU
--CPU突然增高,由以下几个原因导致:
1、短时间内大量并发热点块争用,锁竞争,软/硬解析过多
2、SQL中包含大量jion查询,sort排序,聚合函数甚至是笛卡尔乘积
3、由于数据变动导致的大量的突发表维护操作(auto vacuum/analyze)
4、数据碎片较多的表,维护长版本链的消耗
5、扫描数据量较大的表的同时,存在对表的sort,hash等,也会占用较大cpu资源
--CPU检查:
top命令
htop工具
## DISK IO
--除了CPU增长外,磁盘负载的突然提升,也会导致SQL运行变慢,由以下几个原因导致:
1、大型运维操作争用(vacuum freeze/full);
2、由于数据倾斜导致的SQL执行计划变化,使用了全表扫描替代索引扫描;
3、排序或子查询的数据量较大,排序结果集发生了落盘;
4、定时任务或定期报表等OLAP导致的IO争用;
5、如果服务器是虚拟机,也请检查是否存在iops上限设置等问题
--DISK检查:
iostat -dxt 1 10
## MEM
--由于MogDB使用max_process_memory限制了数据库计算节点可用的最大物理内存,一般情况下不会出现由于内存不足导致的问题,如果出现了内存被MogDB进程大量使用的问题,需要尽快排查是否存在OOM(out of memory)
-- 内存检查:
ps auxw|head -1;ps auxw|sort -rn -k4|head -10
对系统负载情况简单摸底后,可以通过数据库pg_locks视图确认是否存在锁阻塞导致了SQL的体感变慢。也可以通过设置lockwait_timeout和update_lockwait_timeout两个参数,规避该类问题的发生
--查看是否存在锁阻塞
with tl as (select a.pid,usename,granted,locktag,query_start,query,mode,a.state
from pg_locks l,pg_stat_activity a
where l.pid=a.pid and locktag in(select locktag from pg_locks where granted='f'))
select ts.pid locker_pid,ts.usename locker_user,ts.query_start locker_query_start,ts.granted locker_granted,ts.query locker_query,ts.mode locker_mode,tt.pid locked_pid,tt.query locked_query,tt.query_start locked_query_start,tt.granted locked_granted,tt.usename locked_user,tt.mode locked_mode,extract(epoch from now() - tt.query_start) as locked_times
from (select * from tl where granted='t') as ts,(select * from tl where granted='f') tt
where ts.locktag=tt.locktag order by 1;

当排除锁阻塞问题后,接下来使用数据库pg_stat_activity视图对当前活动会话的并发压力进行态势感知,提取故障/慢SQL。
--检查数据库并发情况
select datname,usename,state,query,count(*) from pg_stat_activity where state='active' group by datname,usename,state,query order by 5;

--根据运行时间阈值定向查找慢SQL,比如已经运行了超过5min的SQL
select pid,datname,usename,state,query,query_start from pg_stat_activity where state='active' and query_start < (now() - interval '5 minutes');

--根据pid查询事务链接信息,及时间节点信息
select pid,datname,usename,client_addr,application_name,backend_start,xact_start,query_start,state_change,query,state from pg_stat_activity where pid=140433990350592;

根据从pg_stat_activity数据字典中的提取的慢SQL(或由业务侧直接定位到的慢SQL),接下来就可以诊断执行计划了。但是需要注意的是正在执行的SQL和历史执行过的SQL的query plan,需要在两张不同数据字典查询。同时需要注意只有sysadmin权限可以查询视图。
--正在执行的SQL
--前置参数:
use_workload_manager:资源负载管理总开关,默认on
--如果能筛选出独立的长时间query,根据pid查询语句:
select dbname,
schemaname,
username,
application_name,
client_addr,
pid,
start_time,
duration,
estimate_total_time,
estimate_left_time,
round(estimate_left_time/estimate_total_time,2)||'%' exec_percent,
max_cpu_time/1000000 max_cpu_time_s,
max_peak_memory max_mem_mb,
max_spill_size max_spill_space_mb,