1. PostgreSQL DBA日常运维必备SQL大全
作为PostgreSQL数据库管理员,日常工作中需要频繁使用各种SQL来监控数据库状态、排查性能问题、优化资源使用。经过多年实战积累,我整理了一套非常实用的DBA常用SQL集合,涵盖了数据库监控、性能分析、资源优化等各个方面。
这些SQL大多以视图或存储过程的形式存在,可以直接在数据库中创建,方便日常调用。下面我将分类详细介绍这些SQL的使用场景和实现原理。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据库基础监控视图
2.1 无效索引检查
sql复制CREATE VIEW dba.invalid_index AS
SELECT indisvalid, indexrelid::regclass, indrelid::regclass, pg_get_indexdef(indexrelid)
FROM pg_index
WHERE NOT indisvalid;
这个视图用于检查数据库中所有无效的索引。当索引被标记为无效(indisvalid=false)时,查询优化器会忽略这些索引,但它们仍然占用存储空间。定期检查并删除无效索引可以回收存储空间。
2.2 只读冲突统计
sql复制CREATE VIEW dba.ro_conflicts AS
SELECT datname,
pg_stat_get_db_conflict_all(oid) conflict_all,
pg_stat_get_db_conflict_bufferpin(oid) conflict_bufferpin,
pg_stat_get_db_conflict_lock(oid) conflict_lock,
pg_stat_get_db_conflict_snapshot(oid) conflict_snapshot,
pg_stat_get_db_conflict_startup_deadlock(oid) conflict_deadlock,
pg_stat_get_db_conflict_tablespace(oid) conflict_tbs
FROM pg_database;
该视图显示各数据库发生的冲突统计信息,包括:
- bufferpin冲突:由于缓冲区pin等待导致的冲突
- 锁冲突:由于锁等待导致的冲突
- 快照冲突:由于快照不一致导致的冲突
- 启动死锁:启动过程中的死锁
- 表空间冲突:表空间相关的冲突
高冲突率可能表明应用程序存在并发问题。
2.3 事务处理速率(TPS)监控
sql复制CREATE OR REPLACE PROCEDURE dba.tps() AS $$
DECLARE
v1 int8;
v2 int8;
BEGIN
SELECT txid_snapshot_xmax(txid_current_snapshot()) INTO v1;
COMMIT;
PERFORM pg_sleep(1);
SELECT txid_snapshot_xmax(txid_current_snapshot()) INTO v2;
COMMIT;
RAISE NOTICE 'tps: %', v2-v1;
END;
$$ LANGUAGE plpgsql;
这个存储过程通过比较1秒内事务ID的增长量来计算TPS(每秒事务数)。执行时会输出类似"NOTICE: tps: 125"的信息,表示当前TPS为125。
注意:这种方法计算的是数据库整体TPS,如果需要计算特定应用的TPS,应该使用应用层的监控指标。
3. 复制与高可用监控
3.1 主从复制延迟监控
在主节点上创建以下视图监控复制延迟:
sql复制CREATE VIEW dba.ro_delay AS
SELECT application_name, client_addr, client_port, write_lag, replay_lag, sync_state
FROM pg_stat_replication;
各字段含义:
- write_lag: 主库写入WAL到备库接收WAL的延迟
- replay_lag: 备库接收WAL到应用WAL的延迟
- sync_state: 复制同步状态(同步/异步)
在备节点上创建以下视图监控接收和回放延迟:
sql复制-- 检查备库replay比receive的延迟
CREATE VIEW dba.node_delay AS
SELECT * FROM pg_size_pretty(pg_wal_lsn_diff(pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn())) AS t(delay);
-- 检查备库接收WAL比主库产生WAL的延迟
CREATE VIEW dba.ro_delay_on_standby AS
SELECT pg_size_pretty(pg_wal_lsn_diff(latest_end_lsn, received_lsn))
FROM pg_stat_wal_receiver;
3.2 备库WAL接收和回放带宽监控
sql复制-- 备库WAL接收带宽
CREATE OR REPLACE PROCEDURE dba.wal_receive_bw()
LANGUAGE plpgsql
AS $procedure$
DECLARE
v1 pg_lsn;
v2 pg_lsn;
BEGIN
SELECT pg_last_wal_receive_lsn() INTO v1;
COMMIT;
PERFORM pg_sleep(1);
SELECT pg_last_wal_receive_lsn() INTO v2;
COMMIT;
RAISE NOTICE 'wal receive bw: %/s', pg_size_pretty(pg_wal_lsn_diff(v2,v1));
END;
$procedure$;
-- 备库WAL回放带宽
CREATE OR REPLACE PROCEDURE dba.wal_replay_bw()
LANGUAGE plpgsql
AS $procedure$
DECLARE
v1 pg_lsn;
v2 pg_lsn;
BEGIN
SELECT pg_last_wal_replay_lsn() INTO v1;
COMMIT;
PERFORM pg_sleep(1);
SELECT pg_last_wal_replay_lsn() INTO v2;
COMMIT;
RAISE NOTICE 'wal replay bw: %/s', pg_size_pretty(pg_wal_lsn_diff(v2,v1));
END;
$procedure$;
这两个存储过程分别测量备库接收和应用WAL的速率,对于诊断复制性能问题非常有用。
4. 性能分析与SQL监控
4.1 高耗时SQL查询
sql复制CREATE VIEW dba.topsql AS
SELECT calls, total_time, total_time/calls, query
FROM pg_stat_statements
WHERE query !~ 'rds'
ORDER BY total_time DESC
LIMIT 5;
此视图显示总耗时最高的5条SQL,基于pg_stat_statements扩展收集的统计信息。字段包括:
- calls: 执行次数
- total_time: 总耗时(毫秒)
- total_time/calls: 平均耗时
- query: SQL文本
注意:使用前需确保已安装pg_stat_statements扩展并正确配置。
4.2 QPS(每秒查询数)监控
sql复制CREATE VIEW dba.qps AS
WITH a AS (SELECT sum(calls) s FROM pg_stat_statements),
b AS (SELECT sum(calls) s FROM pg_stat_statements, pg_sleep(1))
SELECT b.s-a.s AS qps FROM a,b;
这个视图通过比较1秒前后SQL执行总数的差值来计算QPS。
4.3 活跃会话监控
sql复制-- 活跃会话数
CREATE VIEW dba.session_acting_cnt AS
SELECT count(*)
FROM pg_stat_activity
WHERE wait_event IS NOT NULL
AND (backend_xid IS NOT NULL OR backend_xmin IS NOT NULL);
-- 活跃会话详情
CREATE VIEW dba.sessions AS
SELECT *
FROM pg_stat_activity
WHERE wait_event IS NOT NULL
AND (backend_xid IS NOT NULL OR backend_xmin IS NOT NULL);
活跃会话数如果持续超过CPU核心数,说明数据库负载较高,可能需要优化。
4.4 锁等待分析
sql复制CREATE VIEW dba.locks AS
WITH t_wait AS (
SELECT a.mode, a.locktype, a.database, a.relation, a.page, a.tuple, a.classid, a.granted,
a.objid, a.objsubid, a.pid, a.virtualtransaction, a.virtualxid, a.transactionid, a.fastpath,
b.state, b.query, b.xact_start, b.query_start, b.usename, b.datname, b.client_addr, b.client_port, b.application_name
FROM pg_locks a, pg_stat_activity b
