PostgreSQL 日常巡检&问题排查文档

文档说明

1.适用版本:PostgreSQL 12/13/14/15/16/18 源码编译/二进制部署

2.巡检范围:服务器主机资源、数据库实例状态、连接、锁、长事务、慢SQL、表/索引膨胀、WAL主从、权限、自动清理等全维度

3.使用场景:日常定时巡检、故障排查、上线前核查、月度运维报告

4.规范:每条巡检项包含执行命令/SQL、正常标准、异常处理方案

1.1 主机信息巡检(root执行)

1.1.1 CPU检查

前置工具安装

yum install -y sysstat
# Ubuntu
apt install -y sysstat

查看空闲CPU

# 空闲CPU占比
mpstat | sed -n '3,$p' | awk -F' ' '{print $13}'
# 用户CPU占用
mpstat | sed -n '3,$p' | awk -F' ' '{print $12}'
# CPU核心总数
echo 'CPU CORE:' && cat /proc/cpuinfo|grep processor|wc -l

正常标准:空闲CPU>20%
异常处理top -c 定位高CPU进程,终止无效长SQL会话

1.1.2. 内存检查

free -m

正常标准:空闲内存占总内存>30%
异常处理:top查看内存占用进程,清理长时间空闲数据库连接

1.1.3 磁盘空间检查

df -lh

正常标准:磁盘已用空间<70%
异常处理:清理无用日志/备份,扩容磁盘

1.1.4 磁盘IO检查

iostat -x | sed -n '6,$p' | awk -F' ' '{print $1,$13,$14}'

输出字段:磁盘设备、%iowait、%util
正常标准:%util持续低于70%
异常处理:优化慢SQL、减少大批量DML、扩容高速存储

1.1.5 数据库端口监听检查


netstat -tanp | grep 'LISTEN' | grep '5432'

正常标准:tcp4、tcp6双协议正常监听5432
异常处理

1.检查数据库是否正常启动

2.核对postgresql.conf listen_addressesport 参数

1.1.6 PostgreSQL后台进程完整性检查

ps -ef | grep "checkpointer|background writer|walwriter|autovacuum launcher|archiver|stats collector|logical replication launcher|logger" | grep -v grep

正常标准:所有核心后台进程全部存在
异常处理:数据库异常退出,执行 systemctl restart postgresql-xx 重启实例

1.2 数据库巡检(su - postgres 登录psql执行)

1.2.1 实例基础信息、运行时长、主备标识


select
     to_char(now(),'yyyy-mm-dd hh24:mi:ss') "巡检时间"
    ,to_char(pg_postmaster_start_time(),'yyyy-mm-dd hh24:mi:ss') "pg_start_time(启动时间)"
    ,now()-pg_postmaster_start_time() "pg_running_time(运行时长)"
    ,version() "server_version(数据库版本)"
    ,(case when pg_is_in_recovery()='f' then 'primary' else 'standby' end ) as  "primary_or_standby(主/备)"
;

正常标准:实例正常运行,无崩溃重启记录
异常处理:查看pg日志,修复配置/磁盘/内核问题后重装/重启数据库

1.2.2 读取postgresql.conf全部配置

select
     to_char(now(),'yyyy-mm-dd hh24:mi:ss') "巡检时间"
    ,sourceline "sourceline(行号)"
    ,name "para(参数名)"
    ,setting "value(参数值)"
from pg_file_settings
order by sourceline;

正常标准:内存、连接、日志、WAL参数符合业务规格
异常处理:修改$PGDATA/postgresql.conf,重载/重启数据库

pg_ctl restart -mf

1.2.3 pg_hba.conf 访问认证规则核查

select
     to_char(now(),'yyyy-mm-dd hh24:mi:ss') "巡检时间"
    ,line_number "line_number(行号)"
    ,type "type(连接类型)"
    ,database "database(数据库名)"
    ,user_name "user_name(用户名)"
    ,address "address(ip地址)"
    ,netmask "netmask(子网掩码)"
    ,auth_method "auth_method(认证方式)"
from pg_hba_file_rules
order by line_number;

正常标准:外网非本地套接字连接统一使用 scram-sha-256 认证
异常处理:编辑pg_hba.conf,重载配置生效

pg_ctl reload

1.2.4 核心关键配置项核查

select
     to_char(now(),'yyyy-mm-dd hh24:mi:ss') "巡检时间"
    ,name
    ,setting
from
    pg_settings a
where a.name in (
  'data_directory',
  'port',
  'client_encoding',
  'config_file',
  'hba_file',
  'ident_file',
  'archive_mode',
  'logging_collector',
  'log_directory',
  'log_filename',
  'log_truncate_on_rotation',
  'log_statement',
  'log_min_duration_statement',
  'max_connections',
  'listen_addresses'
)
order by name;

正常标准:目录、端口、日志、最大连接、监听地址配置合规
异常处理:修改对应参数后重载/重启数据库

1.2.5 主从WAL同步状态

主库执行(查看备库复制流)

select
    state "state(WAL发送状态编码)"
    ,sync_state "sync_state(同步状态编码)"
    ,round(pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) /(1024 * 1024),2) as "slave_latency_mb(同步延迟_MB)"
from pg_stat_replication;

备库执行(查看WAL接收进程)

select
     status "status(WAl接收状态)"
    ,'async' "sync_state(同步状态编码)"
    ,sender_host "sender_host(主库IP)"
from pg_stat_wal_receiver;

正常标准:主库state=streaming,同步延迟<100MB;备库接收进程正常运行
异常处理:检查网络、wal_keep_size、复制槽、归档配置

1.2.6 表空间巡检

SELECT

    to_char(now(),'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",

    spcname AS "Name(表空间名称)",

    pg_catalog.pg_get_userbyid(spcowner) AS "Owner(拥有者)",

    pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS "Size(表空间大小)"

FROM pg_catalog.pg_tablespace

ORDER BY pg_catalog.pg_tablespace_size(oid) DESC;

1.2.7 数据库连接数管理

总连接统计

select
     to_char(now(),'yyyy-mm-dd hh24:mi:ss') "巡检时间"
    ,max_conn "max_conn(最大连接数)"
    ,now_conn "now_conn(当前连接数)"
    ,max_conn - now_conn "remain_conn(剩余连接数)"
from (
    select
         setting::int8 as max_conn
        ,(select count(*) from pg_stat_activity ) as now_conn
    from pg_settings
    where name = 'max_connections'
) a
;

按数据库分组连接数

SELECT
    datname AS "数据库名",
    COUNT(*) AS "连接数"
FROM pg_stat_activity
WHERE datname IS NOT NULL
GROUP BY datname
ORDER BY COUNT(*) DESC;

按用户分组连接数

SELECT usename, COUNT(*) AS connection_count  
FROM pg_stat_activity  
GROUP BY usename;

单库空闲连接批量终止(示例库test_db

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'test_db'
  AND state = 'idle'
  AND pid <> pg_backend_pid();

全局终止30分钟以上空闲连接

DO
$$
DECLARE  
    r RECORD;  
BEGIN  
    FOR r IN (  
        SELECT pid  
        FROM pg_stat_activity  
        WHERE state = 'idle'  
          AND now() - state_change > INTERVAL '30 minutes'  
          AND pid <> pg_backend_pid()  
    ) LOOP  
        PERFORM pg_terminate_backend(r.pid);  
    END LOOP;  
END
$$;

正常标准:当前连接数<最大连接数90%
异常处理:终止长期空闲连接,业务高峰期可临时调高max_connections

1.2.8 锁表、阻塞会话完整巡检

1. 独占锁/行排他锁查询(阻塞业务核心)

SELECT
    to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
    a.relname AS "表名",
    b.nspname AS "模式名",
    c.rolname AS "用户名",
    d.locktype AS "锁对象类型",
    d.mode AS "锁模式",
    d.pid AS "进程PID",
    e.query AS "阻塞SQL",
    age(now(), e.query_start) AS "锁持有时长"
FROM
    pg_class a
INNER JOIN
    pg_namespace b ON (a.relnamespace = b.oid)
INNER JOIN
    pg_roles c ON (a.relowner = c.oid)
INNER JOIN
    pg_locks d ON (a.oid = d.relation)
LEFT JOIN
    pg_stat_activity e ON (d.pid = e.pid)
WHERE
    d.mode IN ('AccessExclusiveLock', 'RowExclusiveLock')
    AND e.pid <> pg_backend_pid()
ORDER BY "锁持有时长" DESC;

2. 批量杀掉所有独占锁会话

DO $$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN (
        SELECT d.pid AS pid
        FROM pg_class a
        INNER JOIN pg_namespace b ON a.relnamespace = b.oid
        INNER JOIN pg_roles c ON a.relowner = c.oid
        INNER JOIN pg_locks d ON a.oid = d.relation
        LEFT JOIN pg_stat_activity e ON d.pid = e.pid
        WHERE d.mode IN ('AccessExclusiveLock', 'RowExclusiveLock')
    ) LOOP
        PERFORM pg_terminate_backend(rec.pid);
    END LOOP;
END $$;

3. 指定数据库批量释放锁(替换库名test_db

DO $$
DECLARE
    rec RECORD;
BEGIN
    FOR rec IN (
        SELECT d.pid AS pid, a.relname, b.nspname, c.rolname, e.query, age(now(), e.query_start) lock_duration
        FROM pg_class a
        INNER JOIN pg_namespace b ON a.relnamespace = b.oid
        INNER JOIN pg_roles c ON a.relowner = c.oid
        INNER JOIN pg_locks d ON a.oid = d.relation
        LEFT JOIN pg_stat_activity e ON d.pid = e.pid
        WHERE d.mode IN ('AccessExclusiveLock', 'RowExclusiveLock')
        AND e.datname = 'test_db'
    ) LOOP
        RAISE NOTICE '终止PID:% 表%.% 锁时长:%', rec.pid, rec.nspname, rec.relname, rec.lock_duration;
        PERFORM pg_terminate_backend(rec.pid);
    END LOOP;
END $$;

锁操作区分

  • pg_cancel_backend(pid):仅取消当前SQL,会话保留
  • pg_terminate_backend(pid):直接断开整个数据库会话,释放全部锁
    正常标准:无长期AccessExclusiveLock独占锁
    异常处理:确认业务无影响后批量终止阻塞PID

1.2.9 长时间空闲连接Top5(超过5分钟)

SELECT
    TO_CHAR(NOW(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",
    a.datname AS "数据库名",
    a.pid AS "进程PID",
    b.rolname AS "用户名",
    a.client_addr AS "客户端IP",
    TO_CHAR(a.state_change, 'yyyy-mm-dd hh24:mi:ss') AS "空闲起始时间",
    a.query AS "最后执行SQL"
FROM pg_stat_activity a
INNER JOIN pg_roles b ON a.usesysid = b.oid
WHERE a.state = 'idle'
AND a.state_change < CURRENT_TIMESTAMP - INTERVAL '5 min'
ORDER BY current_timestamp-state_change DESC
LIMIT 5;

正常标准:无超过30分钟空闲连接
异常处理:批量终止空闲会话释放连接资源

1.2.10 长事务 Top5(idle in transaction)

SELECT   
    to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",  
    a.datname AS "数据库名",  
    a.pid AS "进程PID",  
    b.rolname AS "用户名",  
    a.client_addr AS "客户端IP",  
    to_char(a.state_change, 'yyyy-mm-dd hh24:mi:ss') AS "事务空闲起始时间",  
    a.query AS "未提交事务SQL"
FROM   
    pg_stat_activity a  
INNER JOIN   
    pg_roles b ON a.usesysid = b.oid  
WHERE   
    a.state IN ('idle in transaction', 'idle in transaction (aborted)')  
    AND a.state_change < current_timestamp - INTERVAL '5 min'  
ORDER BY   
    current_timestamp - a.state_change DESC  
LIMIT 5;

正常标准:不存在超过5分钟未提交长事务
异常处理pg_terminate_backend(pid) 终止会话,避免快照膨胀、表膨胀

1.2.11 慢SQL活跃会话Top5(执行超5分钟)

SELECT   
    to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",  
    a.datname AS "数据库名",  
    a.pid AS "进程PID",  
    b.rolname AS "用户名",  
    a.client_addr AS "客户端IP",  
    a.wait_event_type AS "等待类型",  
    a.wait_event AS "等待事件",  
    SUBSTRING(a.query,1,200) AS "执行SQL"
FROM   
    pg_stat_activity a  
LEFT JOIN   
    pg_roles b ON (a.usesysid = b.oid)  
WHERE   
    a.state = 'active'  
AND   
    a.state_change < current_timestamp - INTERVAL '5 min'  
AND   
    a.datname IS NOT NULL  
ORDER BY   
    a.state_change DESC  
LIMIT 5;

正常标准:无执行超过5分钟的活跃SQL
异常处理:优化索引、拆分大事务、终止卡死查询

1.2.12 数据库总对象数量统计

select to_char(now(),'yyyy-mm-dd hh24:mi:ss') "巡检时间"
    ,current_database()
    ,sum(obj_num) "obj_num(总对象数)"
from (
    select count(1) obj_num from pg_class
    union all
    select count(1) from pg_proc
) a
;

正常标准:单库总对象不超过5万
异常处理:清理无用临时表、废弃存储过程

1.2.13 数据表膨胀巡检

SELECT

    to_char(now(), 'yyyy-mm-dd hh24:mi:ss') AS "巡检时间",

    current_database() AS current_database,

    relname AS "table_name(表名)",

    schemaname AS "schema_name(模式名)",

    pg_size_pretty(pg_relation_size((schemaname || '.' || relname)::regclass)) AS "table_size(表大小)",

    n_dead_tup AS "n_dead_tup(无效记录数)",

    n_live_tup AS "n_live_tup(有效记录数)",

    to_char(

        ROUND(

            (n_dead_tup * 1.0 / NULLIF(n_live_tup + n_dead_tup, 0)) * 100,

            2

        ),

        'fm990.00'

    ) AS "dead_rate(无效记录比例%)"

FROM

    pg_stat_all_tables

WHERE

    (n_live_tup + n_dead_tup) <> 0

    AND schemaname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')

ORDER BY

    (n_dead_tup * 1.0 / NULLIF(n_live_tup + n_dead_tup, 0)) DESC;

正常标准:死元组占比<10%,autovacuum正常清理
异常处理

1.常规回收空间:VACUUM ANALYZE 表名;

2.彻底回收空间返还操作系统(锁表,业务低峰执行):VACUUM FULL ANALYZE 表名;

1.2.14 索引膨胀完整查询

select
  to_char(now(),'yyyy-mm-dd hh24:mi:ss') "巡检时间",
  current_database() AS db, schemaname, tablename,bs, reltuples::bigint AS tups, relpages::bigint AS pages, otta,
  ROUND(CASE WHEN otta=0 OR sml.relpages=0 OR sml.relpages=otta THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS tbloat,
  CASE WHEN relpages < otta THEN 0 ELSE relpages::bigint - otta END AS wastedpages,
  CASE WHEN relpages < otta THEN 0 ELSE bs*(sml.relpages-otta)::bigint END AS wastedbytes,
  CASE WHEN relpages < otta THEN $$0 bytes$$::text ELSE (bs*(relpages-otta))::bigint || $$ bytes$$ END AS wastedsize,
  iname, ituples::bigint AS itups, ipages::bigint AS ipages, iotta,
  ROUND(CASE WHEN iotta=0 OR ipages=0 OR ipages=iotta THEN 0.0 ELSE ipages/iotta::numeric END,1) AS ibloat,
  CASE WHEN ipages < iotta THEN 0 ELSE ipages::bigint - iotta END AS wastedipages,
  CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta) END AS wastedibytes,
  CASE WHEN ipages < iotta THEN $$0 bytes$$ ELSE (bs*(ipages-iotta))::bigint || $$ bytes$$ END AS wastedisize,
  CASE WHEN relpages < otta THEN
    CASE WHEN ipages < iotta THEN 0 ELSE bs*(ipages-iotta::bigint) END
    ELSE CASE WHEN ipages < iotta THEN bs*(relpages-otta::bigint)
      ELSE bs*(relpages-otta::bigint + ipages-iotta::bigint) END
  END AS totalwastedbytes
FROM (
  SELECT
    nn.nspname AS schemaname,
    cc.relname AS tablename,
    COALESCE(cc.reltuples,0) AS reltuples,
    COALESCE(cc.relpages,0) AS relpages,
    COALESCE(bs,0) AS bs,
    COALESCE(CEIL((cc.reltuples*((datahdr+ma-
      (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)),0) AS otta,
    COALESCE(c2.relname,$$?$$) AS iname, COALESCE(c2.reltuples,0) AS ituples, COALESCE(c2.relpages,0) AS ipages,
    COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta
  FROM
     pg_class cc
  JOIN pg_namespace nn ON cc.relnamespace = nn.oid AND nn.nspname <> $$information_schema$$
  LEFT JOIN
  (
    SELECT
      ma,bs,foo.nspname,foo.relname,
      (datawidth+(hdr+ma-(case when hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,
      (maxfracsum*(nullhdr+ma-(case when nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2
    FROM (
      SELECT
        ns.nspname, tbl.relname, hdr, ma, bs,
        SUM((1-coalesce(null_frac,0))*coalesce(avg_width, 2048)) AS datawidth,
        MAX(coalesce(null_frac,0)) AS maxfracsum,
        hdr+(
          SELECT 1+count(*)/8
          FROM pg_stats s2
          WHERE null_frac<>0 AND s2.schemaname = ns.nspname AND s2.tablename = tbl.relname
        ) AS nullhdr
      FROM pg_attribute att
      JOIN pg_class tbl ON att.attrelid = tbl.oid
      JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
      LEFT JOIN pg_stats s ON s.schemaname=ns.nspname
      AND s.tablename = tbl.relname
      AND s.inherited=false
      AND s.attname=att.attname,
      (
        SELECT
          (SELECT current_setting($$block_size$$)::numeric) AS bs,
            CASE WHEN SUBSTRING(SPLIT_PART(v, $$ $$, 2) FROM $$#"[0-9]+.[0-9]+#"%$$ for $$#$$)
              IN ($$8.0$$,$$8.1$$,$$8.2$$) THEN 27 ELSE 23 END AS hdr,
          CASE WHEN v ~ $$mingw32$$ OR v ~ $$64-bit$$ THEN 8 ELSE 4 END AS ma
        FROM (SELECT version() AS v) AS foo
      ) AS constants
      WHERE att.attnum > 0 AND tbl.relkind=$$r$$
      GROUP BY 1,2,3,4,5
    ) AS foo
  ) AS rs
  ON cc.relname = rs.relname AND nn.nspname = rs.nspname
  LEFT JOIN pg_index i ON indrelid = cc.oid
  LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid
) AS sml
order by wastedbytes desc limit 20;

异常处理
无锁重建索引(业务低峰推荐):

REINDEX INDEX CONCURRENTLY 索引名;
REINDEX TABLE CONCURRENTLY 表名;

1.2.15 库/表/索引大小查询()

1.单库大小


SELECT datname, pg_size_pretty(pg_database_size(datname)) AS size FROM pg_database;

2.单表总大小(含索引+toast)


select pg_size_pretty(pg_total_relation_size('public.表名'));

3.全表空间排序


SELECT

    format('%I.%I', table_schema, table_name) AS table_name,

    pg_size_pretty(pg_table_size((format('%I.%I', table_schema, table_name))::regclass)) AS table_size,

    pg_size_pretty(pg_indexes_size((format('%I.%I', table_schema, table_name))::regclass)) AS indexes_size,

    pg_size_pretty(pg_total_relation_size((format('%I.%I', table_schema, table_name))::regclass)) AS total_size

FROM information_schema.tables

WHERE table_schema NOT IN ('pg_catalog', 'information_schema')

  AND table_type = 'BASE TABLE'  -- 仅普通表

ORDER BY pg_total_relation_size((format('%I.%I', table_schema, table_name))::regclass) DESC;

1.2.16 Autovacuum自动清理监控

1. 正在执行的vacuum进度


SELECT p.pid,
p.datname,
p.query,
p.backend_type,
a.phase,
a.heap_blks_scanned / a.heap_blks_total::float * 100 AS "% scanned",
a.heap_blks_vacuumed / a.heap_blks_total::float * 100 AS "% vacuumed",
pg_size_pretty(pg_table_size(a.relid)) AS "table size",
pg_get_userbyid(c.relowner) AS owner
FROM pg_stat_activity p
JOIN pg_stat_progress_vacuum a ON a.pid = p.pid
JOIN pg_class c ON c.oid = a.relid
WHERE p.query LIKE 'autovacuum%';

2. 各表死元组、是否需要vacuum


SELECT *
      ,n_dead_tup > av_threshold AS av_needed
      ,CASE
        WHEN reltuples > 0
          THEN round(100.0 * n_dead_tup / (reltuples))
        ELSE 0
        END AS pct_dead
    FROM (
      SELECT N.nspname
        ,C.relname
        ,pg_stat_get_live_tuples(C.oid) AS n_live_tup
        ,pg_stat_get_dead_tuples(C.oid) AS n_dead_tup
        ,C.reltuples AS reltuples
        ,round(current_setting('autovacuum_vacuum_threshold')::INTEGER + current_setting('autovacuum_vacuum_scale_factor')::NUMERIC * C.reltuples) AS av_threshold
        ,date_trunc('minute', greatest(pg_stat_get_last_vacuum_time(C.oid), pg_stat_get_last_autovacuum_time(C.oid))) AS last_vacuum
      FROM pg_class C
      LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
      WHERE C.relkind IN ('r','t')
        AND N.nspname NOT IN ('pg_catalog','information_schema')
        AND N.nspname !~ '^pg_toast'
      ) AS av
ORDER BY av_needed DESC ,n_dead_tup DESC;

1.2.17 锁阻塞链完整排查(定位阻塞源头)


select w1.pid as 等待进程,
w1.mode as 等待锁模式,
w2.usename as 等待用户,
w2.query as 等待会话SQL,
b1.pid as 持有锁进程,
b1.mode 持有锁模式,
b2.usename as 持有锁用户,
b2.query as 持有锁SQL,
b2.application_name 应用名称,
b2.client_addr 客户端IP
from pg_locks w1
join pg_stat_activity w2 on w1.pid=w2.pid
join pg_locks b1 on w1.transactionid=b1.transactionid and w1.pid!=b1.pid
join pg_stat_activity b2 on b1.pid=b2.pid
where not w1.granted;

1.2.18 用户账号、权限、过期时间巡检


SELECT
    r.rolname AS username,
    COALESCE(d.description, '无备注') AS comment,
    r.rolvaliduntil AS password_expire_time,
    r.rolsuper AS is_superuser,
    r.rolcanlogin AS can_login,
    r.rolreplication AS can_replicate,
    r.rolconnlimit AS max_conn_limit
FROM pg_roles r
LEFT JOIN pg_shdescription d ON d.objoid = r.oid
WHERE r.rolcanlogin = true
ORDER BY r.rolname;

正常标准:无过期账号、超级用户数量受控、业务账号连接限制合理
异常处理:重置过期密码、回收多余super权限、限制账号最大连接

1.2.19 临时文件/大查询磁盘占用监控

SELECT * FROM pg_ls_tmpdir();

1.2.20 长事务xmin快照老化监控(防表膨胀核心)

SELECT
    pid,
    usename,
    application_name,
    client_addr,
    backend_xmin,
    age(backend_xmin) AS xmin_age,
    now() - xact_start AS xact_duration,
    state,
    LEFT(query, 100) AS query_preview
FROM pg_stat_activity
WHERE backend_xmin IS NOT NULL
  AND pid <> pg_backend_pid()
ORDER BY age(backend_xmin) DESC;

预防方案(库级别自动超时)

ALTER DATABASE test_db 
SET idle_in_transaction_session_timeout = '3min';
ALTER DATABASE test_db 
SET statement_timeout = '10min';
SELECT pg_reload_conf();

文档使用说明

1.日常巡检:按「1.1主机资源 → 1.2数据库实例」顺序逐条执行核对

2.故障排查:优先执行锁查询、长事务、慢SQL、表膨胀、IO负载

3.自动化适配:所有SQL可封装Shell脚本,定时输出巡检报告

4.生产规范:

  • 禁止频繁执行VACUUM FULL,仅业务低峰使用
  • 锁会话终止前优先确认业务无写入操作
  • 长事务必须设置会话超时自动断开,避免快照膨胀
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

senhai6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值