十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

PostgreSQL 常用命令全解析:从连接到备份恢复的运维实践

PostgreSQL 常用命令全解析:从连接到备份恢复的运维实践 1. 写在前面的几句大实话干了这么多年数据库手里管过的实例怎么也有几十套了PostgreSQL 是我用得最顺手、也最愿意推荐给别人的一套系统。很多朋友一提到 PG第一反应是“功能强、插件多、社区活”但真到上手那天面对黑乎乎的终端窗口第一句命令却不知道该敲什么。也有不少从 MySQL 转过来的老伙计习惯性地用mysql -u root -p到了 PG 这边发现压根不吃这一套瞬间懵了。其实这很正常。PostgreSQL 的命令体系有自己的脾气它不像某些数据库那样“一把梭”而是把连接、角色、权限、备份、调优这些事拆得清清楚楚。你只要把日常最常用的那批命令吃透了后面不管查问题、做迁移、写自动化脚本都顺得很。这篇东西不打算给你堆一份命令大全那没意思。我按照自己平时干活的实际路线把 PG 相关命令整理成一条能直接照着走的操作链路从连库开始到建库建表到权限控制到备份恢复再到性能排查每一段都是实打实用过的。里面还夹了不少踩坑记录——有些错我犯过有些错我见别人犯过你都省得再走一遍弯路。不管你是刚入门的新手还是已经写了好几年 SQL 的老手只要日常需要跟 PostgreSQL 打交道这篇文章应该能帮你把命令这条线彻底理顺。2. 连接管理与日常登录先解决“怎么进得来”的问题2.1 psql 的几条实用连接姿势PostgreSQL 的命令行客户端叫psql这也是你日常跟数据库打交道最频繁的一个工具。先说最基础的几条连接命令这些都是我每天要敲无数遍的东西。# 本地连接默认用户和当前系统用户同名 psql # 指定用户连接指定库 psql -U postgres -d mydb # 远程连接 psql -h 192.168.1.100 -p 5432 -U app_user -d business_db # 连接后直接执行一条 SQL 就退出 psql -h localhost -U postgres -d mydb -c SELECT version(); # 用文件批量执行 SQL psql -h localhost -U postgres -d mydb -f /tmp/init.sql这里有个新手最容易踩的坑PG 默认把“当前操作系统用户名”当作数据库用户名。你在 Linux 上登录用户是root直接敲psql它会默认用root这个数据库角色去连但安装 PG 时并不会自动创建一个叫root的数据库账号所以大概率报错role root does not exist。正确做法是用-U postgres明确指定用户或者先切到postgres系统账号下再敲psql。-p参数是端口PG 默认走 5432。很多从 MySQL 转过来的朋友会习惯性省略端口结果在本机怎么都连不上最后发现是端口写错了或者被防火墙挡了这种低级问题排查起来最耗时间。2.2 连接信息变了先查这几个地方连接不上 PG 的时候别急着怀疑命令写错了。按照我多年踩坑的经验90% 的连接问题都出在三个地方。第一个是pg_hba.conf认证配置。它决定了哪些 IP 能连、用哪种方式认证。很多云服务器默认只允许 localhost 连接远程连不上八成就是这里的配置没放开。改完这个文件记得重启服务或者执行SELECT pg_reload_conf();让配置生效不用整库重启。第二个是listen_addresses。这个参数在postgresql.conf里默认值是localhost意思是不监听外部请求。想从别的机器连过来得把它改成*或者具体的网卡 IP。这个参数属于“改完必须重启”的类型reload都不行我有时候线上改完忘了这茬白等两小时后来专门记到自己的checklist里了。第三个就是最朴素的防火墙问题——云厂商的安全组、本机的 iptables、还有 SELinux任何一个挡在前面PG 都连不进去。检查的顺序我建议是先telnet IP 端口看通不通通了再谈认证和配置。不通的话八成就是网络层面的问题压根还没轮到 PG 出场。注意改pg_hba.conf的时候一定要留一个“后门”也就是确保至少有一条规则能从本机用postgres超级用户登录。你要是把所有规则改坏了又没开第二个会话那就只能上单用户模式修复了那个操作还挺麻烦的。2.3 管理常用内部命令真正进入 psql 命令行之后有一批“反斜杠命令”是提高效率的关键它们不是 SQL但比 SQL 还常用。-- 查看所有数据库 \l -- 切换数据库 \c dbname -- 查看所有表 \dt -- 查看表结构 \d table_name -- 查看所有用户/角色 \du -- 查看当前连接信息 \conninfo -- 看SQL执行耗时 \timing -- 查看命令帮助 \h -- 退出 \q\dt和\d这两个命令几乎天天用。查一个陌生的数据库时我习惯先\dt看有什么表再\d 表名看字段类型心里就有谱了。\timing这个命令很多人不知道打开以后 psql 会在每条 SQL 跑完自动显示耗时排查慢查询时极其好用。3. 数据库与空间的创建管理建库是门手艺活3.1 创建数据库的完整姿势创建数据库就一条CREATE DATABASE命令但后面能挂的参数比你想象的多。我在生产环境常用的姿势是这样的CREATE DATABASE business_db WITH OWNER app_user ENCODING UTF8 LC_COLLATE zh_CN.UTF-8 LC_CTYPE zh_CN.UTF-8 TEMPLATE template0 CONNECTION LIMIT 100;有几个细节值得说道说道。ENCODING必须指定成UTF8不然 PG 默认用的可能是SQL_ASCII将来存中文容易出现乱码和排序问题。LC_COLLATE和LC_CTYPE指定了排序规则和字符分类这俩在建库之后就改不了了只能删库重建所以一开始就得想清楚。想用中文排序就选zh_CN.UTF-8业务上要按英文排就直接用C或者POSIX性能更好但中文排序不太灵活要权衡。TEMPLATE template0是我必加的参数。PG 默认用template1作为模板建库但如果你在这个模板库里加了什么扩展或者自定义对象新建的库都会被带上容易造成“脏库”。template0是纯净版本从它复制出来的库不会继承乱七八糟的修改。CONNECTION LIMIT是连接数上限默认 -1 表示不限。如果这个库是给某个业务线专用的建议设置一个合理上限防止某个应用连接泄漏时把整个实例的连接池干穿拖垮其他库。3.2 删除数据库的正确姿势与误删教训删除数据库的命令看起来就一条DROP DATABASE business_db;但这条命令有几个“前提条件”很容易踩坑。第一只能删除当前没有其他连接会话的数据库。如果你连着 business_db 本身或者有其他应用连着它执行会直接报错。网上那个error 1010 (HY000): error dropping database的报错虽然不是 PG 的但道理是相通的——有会话占着库就删不掉。PG 的报错是database xxx is being accessed by other users。解决办法是先断开所有连接再删-- 强制断开所有连接PG 9.6 以后可用 SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname business_db AND pid pg_backend_pid();然后马上执行 DROP DATABASE。中间最好别停顿因为可能刚好有新的连接抢上来。第二删除数据库需要超级用户权限或者是该库的属主。权限不够的话会看到permission denied to drop database。生产环境删库是高危操作我的习惯是先pg_dump备份然后不是直接 DROP而是改个名“软删除”ALTER DATABASE business_db RENAME TO business_db_archive;确认真没问题了再 DROP。这样一旦发现删错了改个名回来就行了不至于酿成大事故。这个习惯建议每个人都养成操作成本极低但是给了自己一次反悔的机会。3.3 数据库属性的动态调整建库之后想改属性用ALTER DATABASE。常用的几个场景我列一下-- 修改库的owner ALTER DATABASE business_db OWNER TO new_owner; -- 修改连接数限制 ALTER DATABASE business_db CONNECTION LIMIT 200; -- 修改默认表空间 ALTER DATABASE business_db SET TABLESPACE fast_disk;值得留意的是ALTER DATABASE ... SET ...这种写法可以给指定数据库设置不全局生效的参数类似“数据库级别的配置”。比如某个库需要单独调大work_mem就这么写ALTER DATABASE business_db SET work_mem 64MB;这样只影响这个库不影响其他库也不用动全局配置文件非常实用。4. 日常数据操作与查询这些命令撑起80%的活儿4.1 表结构和索引的常用操作建表和索引这种事我猜大部分读者都会但有几个细节我还是要啰嗦一遍因为踩的人实在太多了。-- 标准建表 CREATE TABLE users ( id BIGSERIAL PRIMARY KEY, username VARCHAR(64) NOT NULL UNIQUE, email VARCHAR(128), status SMALLINT DEFAULT 1, created_at TIMESTAMPTZ DEFAULT now() ); -- 修改表结构 ALTER TABLE users ADD COLUMN phone VARCHAR(20); ALTER TABLE users RENAME COLUMN phone TO mobile; ALTER TABLE users DROP COLUMN mobile; -- 创建索引 CREATE INDEX idx_users_created_at ON users (created_at); CREATE UNIQUE INDEX idx_users_email ON users (email);几个要点BIGSERIAL是自增主键的常用写法它会自动创建一个序列。但注意它跟 MySQL 的AUTO_INCREMENT有个重要区别PG 的序列不会跟随事务回滚回退。比如一个事务插了记录序列从 1 跳到 100事务回滚了序列不会回退。这是设计如此不要去纠结也不要去修改它强行调回去反而可能引发主键冲突。索引方面我建议是不要过早建索引。很多新手见到查询慢就加索引结果写放大严重磁盘IO飙升。先EXPLAIN ANALYZE看执行计划确认是全表扫描导致的慢再考虑加索引。另外索引的名字要起得有意义别让数据库自动生成一堆users_email_idx这种后面维护的时候根本分不清哪个是哪个。4.2 数据增删改查与批量写入技巧增删改查这块我直接给一个生产环境常见的场景顺便展示一些通用写法-- 插入ON CONFLICT 处理主键冲突PG 独有特性 INSERT INTO users (id, username, email) VALUES (1, alice, aliceexample.com) ON CONFLICT (id) DO UPDATE SET email EXCLUDED.email; -- 批量插入 INSERT INTO users (username, email) VALUES (bob, bobexample.com), (carol, carolexample.com), (dave, daveexample.com); -- 单条更新 UPDATE users SET status 0 WHERE id 1; -- 删除按条件删除而不是全部清空 DELETE FROM users WHERE status 0 AND created_at now() - interval 90 days;这里的ON CONFLICT是 PG 独有的 upsert 写法非常实用。像定时任务导数据的时候经常要“有就更新、没有就插入”一条 SQL 搞定不用先查再判断。批量插入时数据量特别大建议用 PG 原生的COPY命令比一条条 INSERT 快几个数量级# 从文件批量导入 COPY users FROM /tmp/users.csv WITH (FORMAT csv, HEADER true); # 导出到文件 COPY users TO /tmp/users_out.csv WITH (FORMAT csv, HEADER true);COPY是服务端文件操作权限要求比较高。如果只是客户端本地文件用\copy命令就行。我在做数据迁移的时候特别喜欢用\copy它不需要超级用户普通用户就能操作在 psql 里直接跑非常方便。4.3 查询优化前的关键命令EXPLAIN 和 ANALYZE查询慢是 PG 日常运维里遇到最多的问题而处理慢查询的第一步永远是看执行计划。-- 查看执行计划不带真实执行 EXPLAIN SELECT * FROM users WHERE status 0; -- 查看执行计划并真实执行 EXPLAIN ANALYZE SELECT * FROM users WHERE status 0; -- 格式化输出嵌套关系更清楚PG 12 EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) SELECT * FROM users WHERE status 0;我排查慢 SQL 的固定套路是这样的先跑一条EXPLAIN ANALYZE看有没有全表扫描Seq Scan如果有且表数据量很大那就该建索引接着看有没有Sort操作排序和Hash Join表连接通常这两步是内存和CPU的大户再看行数估算偏差大不大如果 PG 估算的行数跟实际行数差很多说明表统计数据过期了跑一下ANALYZE更新统计信息再说。ANALYZE这个命令极其重要但经常被忽略。它统计表的数据分布信息PG 的规划器靠这些统计信息决定使用哪种执行策略。统计信息不全或者严重过期PG 就会“拍脑袋”选出糟糕的执行计划。所以大数据量变更之后记得跑一下-- 分析单表 ANALYZE users; -- 分析当前库所有表推荐 ANALYZE;我通常在每天的定时维护任务里加一条VACUUM ANALYZE既清理死元组空间又更新统计信息一举两得。5. 账号与权限体系权限管理是安全的第一道关5.1 角色创建与常用属性PG 的权限体系核心是“角色”Role一个角色既可以是登录用户也可以是一组权限的集合甚至两者兼是。这一点跟大多数数据库都有区别理解了这个PG 的权限体系就算通了。-- 创建登录角色 CREATE ROLE app_user WITH LOGIN PASSWORD 强密码; -- 创建具有超级用户权限的角色 CREATE ROLE admin_user WITH SUPERUSER LOGIN PASSWORD 强密码; -- 创建角色时带上常用属性 CREATE ROLE readonly_role WITH LOGIN PASSWORD 只读密码; -- 修改角色密码 ALTER ROLE app_user WITH PASSWORD 新密码; -- 查看角色信息 \du建角色的几个注意点LOGIN属性决定这个角色能不能用来连接数据库。只用来做权限分组的角色就不需要LOGIN。SUPERUSER权限务必非常克制生产环境能不用就不用。超级用户能绕过所有权限检查一旦应用账号被拖库等于把整个实例都送出去了。密码一定要用强密码不要123456。PG 的密码存在pg_authid里虽然有加密保护但弱密码就是门户大开。5.2 数据库和表级别的授权管理PG 的授权体系比 MySQL 细得多可以精确到表、列、甚至行级别。日常用得最多的还是库和表这两个层级。-- 把数据库的使用权限给用户 GRANT CONNECT ON DATABASE business_db TO app_user; -- 把某个 schema 的使用权限给用户 GRANT USAGE ON SCHEMA public TO app_user; -- 给表授权 GRANT SELECT, INSERT, UPDATE, DELETE ON users TO app_user; -- 给序列授权自增主键必须的不然插入会报权限错误 GRANT USAGE ON SEQUENCE users_id_seq TO app_user; -- 一次性给所有表授权 GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_role; -- 撤销权限 REVOKE DELETE ON users FROM app_user;这里有个特别容易踩的坑只给表授了 SELECT、INSERT 等权限忘了给序列授权结果应用一插入数据就报permission denied for sequence。这个报错很多人花了大半天才找到原因其实原理很简单——自增主键要取序列的 nextval没权限去取自然就插不进去了。对只读账号我一般用一个固定模板GRANT CONNECT ON DATABASE business_db TO readonly_role; GRANT USAGE ON SCHEMA public TO readonly_role; GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly_role; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly_role;最后那句ALTER DEFAULT PRIVILEGES很多人会漏它表示“将来新建的表默认给这个角色 SELECT 权限”。如果没有这句DBA 创建新表后只读账号还是查不了这种“查不到新表”的问题排查起来也挺费劲的。5.3 常见权限报错与排查技巧权限问题经典报错我见得最多的有这么几个permission denied for table users——表级权限没给。检查GRANT是否漏了。permission denied for schema public——schema 的 USAGE 权限没给。如果没有这个基础权限后面的表权限全白搭因为用户根本进不了 schema 空间。must be owner of table users——当前角色只是被授权操作但有些操作需要对象属主或者更高权限比如DROP TABLE、ALTER TABLE就要求是属主光有ALL PRIVILEGES都不行。insufficient permission for adding an object to repository database——这种报错也是权限不够通常执行需要特定权限的命令时报的排查方向就是确认当前角色拥有相应对象的属主权或者超级用户。排查权限问题的时候我有个特别好用的命令-- 查看某张表当前的权限分配 \dp users -- 或者用 SQL 查 SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE table_name users;也可以模拟登录用户测试psql -U app_user -d business_db -c SELECT * FROM users LIMIT 1;如果模拟不了用SET ROLE也能模拟SET ROLE app_user; SELECT * FROM users LIMIT 1; RESET ROLE;这个方法我经常用不换连接就能看“用户视角”的权限效果排查非常高效。6. 备份与恢复实战别等出事才想起备份这个事6.1 pg_dump 逻辑备份的完整用法PG 自带pg_dump是逻辑备份的工具也是日常最常用的备份方案。它可以按库导出也可以只导某个表、某个 schema灵活度很高。# 备份整个数据库 pg_dump -h localhost -U postgres -d business_db -F c -f business_db.dump # 只备份表数据不备份结构 pg_dump -h localhost -U postgres -d business_db -t users --data-only -f users_data.sql # 备份成 SQL 纯文本格式方便查看和修改 pg_dump -h localhost -U postgres -d business_db -F p -f business_db.sql # 压缩备份 pg_dump -h localhost -U postgres -d business_db -F c -Z 9 -f business_db.dump.gz关于格式选择我推荐生产环境用-F c自定义格式。这种格式是压缩的体积小而且pg_restore支持灵活恢复可以只恢复某张表也可以并行恢复纯 SQL 文本格式做不到这些。纯 SQL 格式适合导给开发环境、或者让人工审阅数据结构用的场景。-t参数支持指定表名也可以用通配符。我只备份某个业务核心表的时候就用它速度快很多不对整库造成压力。另外强烈建议给备份文件加上时间戳这样既能留多个版本也能追溯历史pg_dump -h localhost -U postgres -d business_db -F c -f business_db_$(date %Y%m%d_%H%M%S).dump6.2 pg_restore 恢复的实用心得恢复备份用pg_restore比直接 psql 灌 SQL 文件灵活得多。# 恢复整个数据库 pg_restore -h localhost -U postgres -d business_db -c -v business_db.dump # 只恢复某张表 pg_restore -h localhost -U postgres -d business_db -t users -v business_db.dump # 遇到错误不中断生产环境慎用 pg_restore -h localhost -U postgres -d business_db --exit-on-error -v business_db.dump # 并行恢复提速明显 pg_restore -h localhost -U postgres -d business_db -j 4 -v business_db.dump-c参数会在恢复前先清理掉目标库里已存在的对象相当于“先删后建”适合恢复到空库或者做整体替换。如果目标库里已经有数据不想动旧的就别加-c。恢复之前目标库要先创建好pg_restore 不会自动建库。目标库建议用template0创建避免模板库的残留影响恢复。并行恢复-j 4是我常用的提速手段但要注意-j参数只对-F c格式生效而且并行恢复不能和-c在某些旧版本上共用PG 14 之后才支持老版本会报错这个要注意。6.3 迁移场景下的命令组合拳做数据迁移的时候我一般组合使用 pg_dump 和 pg_restore流程如下第一步源库备份pg_dump -h 源库IP -U 源用户 -d business_db -F c -f business_db.dump第二步目标库建库psql -h 目标库IP -U postgres -c CREATE DATABASE business_db OWNER app_user ENCODING UTF8 TEMPLATE template0;第三步恢复数据pg_restore -h 目标库IP -U postgres -d business_db -j 4 -v business_db.dump第四步权限修正和校验psql -h 目标库IP -U postgres -d business_db -c GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app_user; psql -h 目标库IP -U app_user -d business_db -c SELECT count(*) FROM users;迁移最怕的就是“看着恢复成功了实际上数据不对”。所以最后一步的校验绝对不能省——至少抽查几张核心表的行数跟源库比一比确认一致了才算完事。别问我怎么知道要校验的问就是有次迁移完少了一个 schema业务上线当天就出事故了。7. 性能排查与日常诊断这些命令救过我很多次7.1 查看当前活跃会话和锁等待数据库卡顿、应用超时九成以上跟锁竞争或者慢查询有关。PG 提供一个随时可查的“活动视图”叫pg_stat_activity这是排查这类问题的第一抓手。-- 查看所有会话 SELECT pid, usename, datname, state, wait_event_type, wait_event, query, now() - query_start AS duration FROM pg_stat_activity WHERE state IS NOT NULL ORDER BY duration DESC;这个查询会把当前所有会话、跑的 SQL、耗时、等待事件全列出来。我一般重点关注两类一类是state active且duration很长的会话这就是慢查询找到对应 SQL 去优化。另一类是wait_event_type Lock的会话这是锁等待说明有事务持锁不释放堵住了后面所有的操作。处理锁等待标准操作是先找到持锁的会话 PID再用pg_terminate_backend终止它-- 终止特定会话 SELECT pg_terminate_backend(12345);这种操作要谨慎终止会话会让那个事务回滚可能影响正在跑的批量任务。但在线业务被锁死的情况下两害相权取其轻该杀就得杀。7.2 VACUUM 和 AUTO VACUUM 的理解VACUUM是 PG 独有的维护命令主要作用是清理“死元组”。PG 的多版本并发控制MVCC机制下被更新或删除的行并不会物理删除而是留下一个死版本让正在进行的老事务还能读到旧数据。死元组如果一直不清理表会越来越大查询性能持续下滑。-- 清理单表 VACUUM users; -- 清理并更新统计信息 VACUUM ANALYZE users; -- 清理整个库 VACUUM;PG 默认开了自动 autovacuum大多数情况下不用手动干预。但有些特殊场景比如大规模批量更新、导入几千万数据autovacuum 可能跟不上这时就需要手动跑一次-- 查看表的大小和死元组比例 SELECT relname, n_live_tup, n_dead_tup, last_vacuum, last_autovacuum FROM pg_stat_user_tables WHERE relname users;如果n_dead_tup特别大而last_vacuum一直没更新说明 autovacuum 可能因为某些原因没跑成这时候手动 VACUUM 一下是有效手段。7.3 监控长事务的必备查询长事务是数据库里的隐形杀手。一个事务开太久不提交会导致几个问题一是锁持有过久阻塞其他会话二是 PG 的 vacuum 无法清理这个事务开始之后产生的死元组导致表膨胀三是如果事务隔离级别是可重复读还可能导致数据不一致。查长事务的命令SELECT pid, usename, datname, state, now() - xact_start AS xact_duration, query FROM pg_stat_activity WHERE xact_start IS NOT NULL AND state IN (active, idle in transaction) ORDER BY xact_duration DESC;我特别关注idle in transaction状态的会话意思是事务开了、但没在执行任何 SQL就这么挂着。这种会话往往更难发现但对系统的伤害一点不小。常见原因就是应用代码里事务忘了提交或者在 Java 里事务抛了异常但没回滚。遇到这种情况确认是残留事务后直接 terminate 就行。注意idle in transaction的会话如果时间很长它的影响不只是自身而是所有依赖于它操作的表的后续操作都会被堵住。所以这个状态要当成“事故信号”来处理不是普通告警。8. 我的日常维护脚本片段最后分享一段我自己常年放在服务器上的组合脚本吧没有花哨的东西但每次维护都能用到。#!/bin/bash # 日常 PG 巡检脚本片段 DB_IPlocalhost DB_USERpostgres DB_NAMEpostgres echo 1. 数据库版本 psql -h $DB_IP -U $DB_USER -d $DB_NAME -c SELECT version(); echo 2. 连接数使用情况 psql -h $DB_IP -U $DB_USER -d $DB_NAME -c SELECT max_conn, current_conn FROM (SELECT count(*) AS current_conn FROM pg_stat_activity) t, (SELECT setting AS max_conn FROM pg_settings WHERE namemax_connections) s; echo 3. 慢查询前5条 psql -h $DB_IP -U $DB_USER -d $DB_NAME -c SELECT pid, state, now()-query_start AS duration, left(query,100) AS query FROM pg_stat_activity WHERE stateactive AND now()-query_start interval 5 seconds ORDER BY duration DESC LIMIT 5; echo 4. 表膨胀情况 top10 psql -h $DB_IP -U $DB_USER -d $DB_NAME -c SELECT schemaname||.||relname AS table_name, n_live_tup, n_dead_tup FROM pg_stat_user_tables WHERE n_live_tup 10000 ORDER BY n_dead_tup DESC LIMIT 10; echo 5. 最近一次自动清理时间 psql -h $DB_IP -U $DB_USER -d $DB_NAME -c SELECT relname, last_vacuum, last_autovacuum FROM pg_stat_user_tables ORDER BY last_autovacuum DESC NULLS LAST LIMIT 5; echo 6. 磁盘占用 top10 psql -h $DB_IP -U $DB_USER -d $DB_NAME -c SELECT schemaname||.||tablename AS table_name, pg_size_pretty(pg_total_relation_size(schemaname||.||tablename)) AS total_size FROM pg_tables WHERE schemaname NOT IN (pg_catalog,information_schema) ORDER BY pg_total_relation_size(schemaname||.||tablename) DESC LIMIT 10;这个脚本我跑了快两年每次维护前先跑一遍哪里有问题基本一目了然。你也不用照抄按自己的业务情况增删就行但核心思路是版本、连接、慢查询、表膨胀、磁盘这几个维度每天过一遍90%的隐患都能提前发现。PG 这套命令体系说多不算多说少也不少但只要把连接、库表、权限、备份、排查这条主链路走通了日常基本就没啥能难住你的了。后面真正遇见新问题的时候多查\h、多看官方文档顺着命令背后的逻辑去推大部分都能解决。
返回列表