当前位置: 首页 > news >正文

如何监控 PostgreSQL 的慢查询和死锁?

1、慢查询

开启慢查询日志

log_min_duration_statement = 1000 # 执行超过1000ms的语句记录日志
log_statement = 'none' # 可选:不记录所有语句,只记录慢查询
log_duration = off # 可选:不记录每条语句的执行时间
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on # 记录锁等待
log_temp_files = 0 # 记录所有临时文件使用
log_autovacuum_min_duration = 0 # 记录所有autovacuum
auto_explain 插件

-- 1. 加载扩展
shared_preload_libraries = 'auto_explain'

-- 2. 配置参数
auto_explain.log_min_duration = '1s' -- 记录超过1秒的查询计划
auto_explain.log_analyze = on -- 包含实际执行统计
auto_explain.log_buffers = on -- 记录缓冲区使用
auto_explain.log_timing = on -- 记录时间统计
auto_explain.log_triggers = on -- 记录触发器
auto_explain.log_verbose = on -- 详细模式
auto_explain.log_nested_statements = on -- 记录嵌套语句
-- 查看当前运行的慢查询
SELECT
pid,
usename,
application_name,
client_addr,
state,
query_start,
now() - query_start as duration,
query
FROM pg_stat_activity
WHERE state = 'active'
AND now() - query_start > interval '5 seconds'
ORDER BY duration DESC;

-- 查看历史慢查询统计
SELECT
query,
calls,
total_exec_time,
mean_exec_time,
rows,
100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
FROM pg_stat_statements
WHERE mean_exec_time > 100 -- 平均执行时间超过100ms
ORDER BY total_exec_time DESC
LIMIT 20;
-- 1. 安装扩展
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

-- 2. 配置
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all
pg_stat_statements.track_utility = on
pg_stat_statements.save = on

-- 3. 查询慢SQL
SELECT
queryid,
query,
calls,
total_exec_time,
mean_exec_time,
stddev_exec_time,
rows,
100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS cache_hit_ratio
FROM pg_stat_statements
WHERE mean_exec_time > 100
ORDER BY total_exec_time DESC
LIMIT 20;
2、死锁

postgresql.conf

log_lock_waits = on -- 记录锁等待
deadlock_timeout = 1s -- 死锁检测间隔(默认1s)
log_min_duration_statement = 0 -- 记录所有语句
log_statement = 'none'
log_line_prefix = '%t [%p]: [%l-1] db=%d,user=%u '
-- 1. 查看当前锁等待
SELECT
blocked_locks.pid AS blocked_pid,
blocked_activity.usename AS blocked_user,
blocking_locks.pid AS blocking_pid,
blocking_activity.usename AS blocking_user,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS blocking_statement,
now() - blocked_activity.query_start AS blocked_duration,
now() - blocking_activity.query_start AS blocking_duration
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity
ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks
ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity
ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.granted;

-- 2. 查看锁等待树
WITH RECURSIVE lock_wait AS (
SELECT
waiting.pid as waiting_pid,
waiting.query as waiting_query,
blocking.pid as blocking_pid,
blocking.query as blocking_query,
1 as depth
FROM pg_locks l1
JOIN pg_stat_activity waiting ON l1.pid = waiting.pid
JOIN pg_locks l2 ON l1.locktype = l2.locktype
AND l1.DATABASE IS NOT DISTINCT FROM l2.DATABASE
AND l1.relation IS NOT DISTINCT FROM l2.relation
AND l1.page IS NOT DISTINCT FROM l2.page
AND l1.tuple IS NOT DISTINCT FROM l2.tuple
AND l1.virtualxid IS NOT DISTINCT FROM l2.virtualxid
AND l1.transactionid IS NOT DISTINCT FROM l2.transactionid
AND l1.classid IS NOT DISTINCT FROM l2.classid
AND l1.objid IS NOT DISTINCT FROM l2.objid
AND l1.objsubid IS NOT DISTINCT FROM l2.objsubid
AND l1.pid != l2.pid
JOIN pg_stat_activity blocking ON l2.pid = blocking.pid
WHERE NOT l1.granted
UNION ALL
SELECT
w.waiting_pid,
w.waiting_query,
l.pid as blocking_pid,
a.query as blocking_query,
w.depth + 1
FROM lock_wait w
JOIN pg_locks l ON w.blocking_pid = l.pid
JOIN pg_stat_activity a ON l.pid = a.pid
WHERE NOT l.granted
)
SELECT * FROM lock_wait ORDER BY depth;

http://www.jsqmd.com/news/413604/

相关文章:

  • 2026年生物菌肥厂家推荐:信和生物科技,多品类有机肥助力农业可持续发展 - 品牌推荐官
  • 2026年电极片厂家实力推荐:郑州康宜健医疗器械,透药/中医定向/乳腺/自粘/理疗电极片全品类覆盖 - 品牌推荐官
  • 多胞胎生育津贴怎么计算,用什么工具查询好 - myqiye
  • git回滚操作 - nova
  • 面向豆包AI的品牌词占位与内容覆盖策略 - 品牌2025
  • 四种恒流源电路及其在集成运放电路中的应用
  • 2026年助听器验配服务推荐:瑞声达助听器厦门专业验配中心,适配儿童/成人/中老年全场景需求 - 品牌推荐官
  • 2026年履带式撒粪车厂家推荐:山东田王装备制造有限公司,果园/农田/大棚全场景适用 - 品牌推荐官
  • 2026年减速机专业厂家推荐:汉森传动设备有限公司,多领域减速机解决方案提供商 - 品牌推荐官
  • 2026年真空泵厂家推荐:淄博双环真空泵厂,环保/小型/水环/无油/节能真空泵全系供应 - 品牌推荐官
  • 2026年郑州婚介所推荐:芳草婚介相亲找对象/脱单/婚恋网/找另一半服务全解析 - 品牌推荐官
  • 2026年高价回收洋酒/老酒/名酒推荐:茅洋名酒回收,全国上门服务,专业鉴定团队保障交易安全 - 品牌推荐官
  • 2026年服装ERP系统推荐:嘉兴市谷泰信息技术有限公司,多品类服装ERP管理软件全覆盖 - 品牌推荐官
  • 解码8051单片机Keil环境搭建与GPIO
  • 2026年热电偶专业厂家推荐:江苏泰而坦自动化科技,铠装/S型/B型/K型等全系列供应 - 品牌推荐官
  • 2026年悬挂/单臂吊/摇臂吊/门式/KBK/抓斗/单梁起重机推荐:山东凌瑞起重集团专业之选 - 品牌推荐官
  • 硕士文献综述怎么写才不踩雷?paperxie 智能文献综述功能,从文献梳理到规范写作一站式搞定
  • 2026西安租车企业实力TOP5|驰行汽服,中高端出行优选标杆 - 朴素的承诺
  • 洞察2026:防火涂料实力厂家排行与核心选购指南 - 2026年企业推荐榜
  • 2026必备!AI论文写作软件 千笔·专业论文写作工具 VS 笔捷Ai,专为本科生打造!
  • OpenClaw(Clawdbot)+Skills零门槛教程:2026年阿里云一键部署超详细
  • 覆盖全场景|西安自驾租车商务租车包车优选,2026实力TOP5揭晓 - 朴素的承诺
  • 2026高职大数据与财务管理专业学习指南
  • 拖延症福音:一键生成论文工具,千笔ai写作 VS 云笔AI,专为本科生打造!
  • 2026年岗亭定制厂家实力推荐:重庆恒尚金属制品有限公司,玻璃/金属雕花板/不锈钢岗亭全系供应 - 品牌推荐官
  • OpenClaw(Clawdbot)+Skills喂饭教程:2026年华为云一键部署毫无压力掌握
  • 实测对比后!万众偏爱的降AI率网站 —— 千笔AI
  • 2026年地埋/PP/一体化/生活/集装箱/医院/农村污水处理设备厂家推荐:山东中侨启迪环保装备 - 品牌推荐官
  • OpenClaw(Clawdbot)+Skills小白教程:2026年京东云一键部署简单易懂掌握
  • 揭秘“学术导航仪”:书匠策AI如何重塑毕业论文写作新范式