GaussDB(DWS)运维实战:从一次慢查询排查,带你玩转pg_stat_activity与锁分析
GaussDB慢查询深度排查从告警到根治的实战指南凌晨3点15分监控系统突然弹出一条红色告警——某核心业务数据库查询响应时间超过15秒。作为值班DBA我迅速连上跳板机发现这不是简单的资源不足问题。通过一系列排查最终定位到一个被遗忘的测试会话持有了生产表的排他锁。这种场景在分布式数据库GaussDB(DWS)中尤为棘手本文将完整还原这次故障排查的全过程并分享一套经过验证的排查方法论。1. 慢查询的初步诊断接到告警后第一件事是确认慢查询的具体特征。在GaussDB中pg_stat_activity视图是我们的第一站。不同于简单的SELECT * FROM pg_stat_activity高级用法需要关注这些关键字段SELECT datname, usename, application_name, client_addr, backend_start, xact_start, query_start, state_change, wait_event_type, wait_event, state, backend_xid, backend_xmin, query, backend_type FROM pg_stat_activity WHERE state ! idle ORDER BY query_start DESC;几个关键观察点backend_start与xact_start的时间差长时间连接但近期无事务可能是连接池泄漏wait_event_type为Lock且持续时间长明确锁等待问题backend_xmin长时间不释放可能是长事务导致vacuum阻塞注意在生产环境查询时务必加上WHERE state ! idle条件避免海量空闲连接干扰分析通过这个查询我很快发现了三个可疑会话一个来自BI工具的查询已运行28分钟两个应用程序会话处于active状态但wait_event显示等待锁一个异常的psql连接已保持6小时但最近2小时无任何活动2. 锁等待的深度分析发现锁等待后需要结合多个系统视图进行交叉分析。GaussDB提供了比开源PostgreSQL更丰富的锁监控视图SELECT l.locktype, l.database, l.relation::regclass, l.page, l.tuple, l.virtualxid, l.transactionid, l.classid, l.objid, l.objsubid, l.mode, l.granted, a.usename, a.query, a.query_start, a.client_addr FROM pg_locks l JOIN pg_stat_activity a ON l.pid a.pid WHERE NOT l.granted ORDER BY a.query_start;关键锁类型解读锁类型典型场景危险等级AccessExclusiveLockALTER TABLE、DROP TABLE★★★★★ExclusiveLockINSERT/UPDATE/DELETE★★★★ShareLockCREATE INDEX CONCURRENTLY★★RowExclusiveLock常规DML操作★通过这个查询确认了阻塞源头一个持有某核心表AccessExclusiveLock的会话。但令人困惑的是这个锁是由一个已经完成的事务持有的——这是GaussDB中典型的锁遗留问题。3. 分布式环境特有的排查挑战在GaussDB的分布式架构下锁问题会更加复杂。我们需要使用专门的分布式锁视图SELECT * FROM pgxc_thread_wait_status WHERE wait_status ! none ORDER BY wait_time DESC;这个视图会显示所有CN和DN节点上的线程等待状态。在我的案例中发现主CN上的会话在等待DN节点的响应其中一个DN节点显示事务超时另一个DN节点有未提交的两阶段事务此时需要结合全局事务ID进行关联查询SELECT gti.gtid, gti.state, a.query, a.query_start, a.client_addr FROM pg_get_transaction_info() gti JOIN pg_stat_activity a ON gti.pid a.pid WHERE gti.state ! idle ORDER BY gti.prepare_time DESC;4. 问题解决与预防措施确认问题会话后终止会话只是治标。完整的解决方案应该包括紧急处理# 先尝试礼貌终止 psql -c SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE pid 12345 AND backend_type client backend # 强制终止DN节点会话 gsql -d postgres -p 25308 -c SELECT pg_terminate_backend(12345)根因分析检查应用连接池配置特别是maxLifetime审核所有DDL操作窗口期验证长事务监控机制是否生效预防改进-- 创建锁等待告警规则 CREATE OR REPLACE FUNCTION check_lock_timeout() RETURNS void AS $$ BEGIN IF EXISTS ( SELECT 1 FROM pg_locks l JOIN pg_stat_activity a ON l.pid a.pid WHERE NOT l.granted AND now() - a.query_start interval 30 seconds ) THEN RAISE EXCEPTION Long running lock wait detected; END IF; END; $$ LANGUAGE plpgsql;监控增强部署Prometheus exporter监控关键指标- name: gaussdb_lock_wait metrics_path: /metrics static_configs: - targets: [gaussdb-exporter:9187] params: query: [ SELECT count(*) as waiting_queries FROM pg_locks WHERE NOT granted ]5. 高级技巧与工具链整合对于复杂问题需要更高级的工具组合性能快照对比# 采集问题时段快照 gs_collector --begin-time2023-07-15 03:00:00 \ --end-time2023-07-15 04:00:00 \ -o /tmp/slow_query_analysisSQL重放分析from gs_xtuner.replay import SQLReplayer replayer SQLReplayer( host127.0.0.1, port25308, databasemy_db ) replayer.replay_from_csv(slow_queries.csv)锁等待可视化 使用Grafana配置锁等待链仪表盘关键SQLWITH lock_chains AS ( SELECT w.pid as waiter, h.pid as holder, h.query as holder_query, w.query as waiter_query, h.xact_start as holder_start, w.query_start as waiter_start FROM pg_locks w JOIN pg_locks h ON w.locktype h.locktype AND w.database h.database AND w.relation h.relation AND w.page h.page AND w.tuple h.tuple AND w.virtualxid h.virtualxid AND w.transactionid h.transactionid AND w.classid h.classid AND w.objid h.objid AND w.objsubid h.objsubid AND w.pid ! h.pid JOIN pg_stat_activity wh ON w.pid wh.pid JOIN pg_stat_activity hh ON h.pid hh.pid WHERE NOT w.granted AND h.granted ) SELECT * FROM lock_chains;6. 架构层面的优化建议经过多次类似事件后我们团队总结出这些最佳实践连接管理所有应用连接必须设置合理的超时参数// JDBC示例 dataSource.setMaxLifetime(1800000); // 30分钟 dataSource.setLeakDetectionThreshold(15000); // 15秒事务规范单个事务持续时间不超过1分钟批量操作使用分批次提交避免在事务中执行用户交互锁优化-- 使用LOCK TABLE WITH TIMEOUT LOCK TABLE orders IN SHARE MODE NOWAIT; -- 大表DDL使用低锁模式 CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders(user_id);监控体系部署三层监控实时锁等待检测30秒长事务告警1分钟连接数趋势预测这套方法在我们生产环境实施后慢查询相关告警减少了80%。最关键的是培养了团队对锁问题的敏感度——现在任何超过5秒的锁等待都会触发值班工程师的排查流程。