资讯动态

PostgreSQL常用命令全解析:从连接到备份恢复与性能诊断

发布时间:2026/10/22 21:58:48 来源:尧图企业网站定制
最近连续有好几个刚接触PostgreSQL的朋友跑来问我同一个问题PG database相关命令到底该怎么记这东西和MySQL不一样命令散落在shell、psql、系统视图里查个东西不知道查哪。这篇就把我实际用下来最频繁、最容易绕晕的PG命令完整梳理一遍覆盖连接、日常操作、信息查询、备份恢复、权限、性能诊断和维护不光给命令还把每类命令背后的设计逻辑和踩过的坑一并讲清楚。1. 先把命令体系捋清楚PG的命令其实分三个入口很多人在PG上觉得命令又多又散根本原因不是命令量大而是没有意识到PG的命令分布在三个完全不同的入口里。三个入口搞清楚了后面所有的记忆负担都会小一大截。第一个入口是操作系统层面的命令行工具。PG安装完以后bin目录下会有一批以pg_开头或者独立命名的可执行文件psql、createdb、dropdb、pg_dump、pg_restore、pg_basebackup、pg_ctl、pg_controldata这种。这一层命令的特点是你在Linux终端或者Windows的cmd里直接敲它们负责的是对数据库实例整体做操作比如创建库、连接库、备份、初始化实例。写自动化脚本的时候打交道的主要是这一层。第二个入口是psql交互终端里的元命令。当你已经用psql连上数据库输入以反斜杠\开头的指令比如\l、\dt、\d、\x、\timing。这些命令不是SQL是psql这个客户端程序自己提供的快捷键本质上是帮你拼SQL查系统表。很多新手容易在这里迷路因为文档里一提到命令就给你一堆反斜杠你以为这些是PG的SQL语法其实它们只活在psql里。第三个入口才是标准SQL包括CREATE TABLE、SELECT、INSERT、UPDATE、GRANT、VACUUM这类。这才是真正对数据库内容生效的东西在任何PG客户端、任何语言驱动里都能执行只是有些命令的名字会让你误以为它不是SQL比如VACUUM、ANALYZE、CHECKPOINT它们确实是SQL命令只是日常用得少。1.1 三个入口怎么配合使用我日常的工作流可以概括成一句话shell层做连接和备份psql层做快速浏览SQL层做真正的操作。举个例子要排查一个线上库为什么慢我会在shell里执行psql连上去然后用psql的\x开启纵向显示再用SQL去查pg_stat_activity视图。整个过程三个入口都会用到谁也不会替代谁。你如果只会其中一个入口就好比只会用手机上的计算器不会用电脑Excel活也能干但效率差很多。还有一件事容易被忽略psql元命令其实是可以传参数的。比如\d requests表名后面可以跟上表名的模糊匹配\dt public.*这样的写法也支持通配符。你不需要精确记住表名单词先用\d通过模糊查询找到想看的表再按回车细化信息这个习惯比死记硬背命令高效得多。1.2 和MySQL的习惯差异端口、大小写、帮助系统从MySQL转过来的人第一个坑就是端口。MySQL默认3306PG默认5432用习惯MySQL的人写连接命令端口经常填错报错以后第一反应是服务没起来实际上服务好好的只是你连错了地方。第二个坑是密码选项。MySQL的-p是指输入密码PG里的-p是指端口。PG里输入密码用的是-W选项或者等它提示。如果你照着MySQL的习惯敲psql -p xxxPG会把你输入的内容当成端口号解析要么报数字格式错误要么直接连接失败。这个真的是高频翻车点。第三个坑是大小写敏感。PG对不带双引号的标识符会强制转为小写。你建表时写CREATE TABLE Users实际存储的名是users如果你真的想要一个大写开头的表名必须写CREATE TABLE Users而且之后每次查询都得带双引号写Users。这个设计和MySQL的宽松策略完全相反SQL看起来一样行为却完全不同。至于帮助系统psql里输入?可以看所有元命令的帮助输入\help SELECT可以看某个SQL语句的语法输入\h可以列出所有SQL命令。这套帮助系统比很多图形化工具还好用强烈建议养成先help再动手的习惯。1.3 搭建自己的速查路径在学习阶段不需要把每个命令背下来但是脑子里要有一张索引表想创建数据库去哪查、想改密码去哪查、想备份去哪查、想杀会话去哪查。每类问题只需要记住一个入口和两三个关键命令就够了剩下的相信?、\h和系统视图。我自己在服务器上长期保存着一个笔记文件里面分了四块日常管理命令、诊断查询SQL、备份恢复命令、权限模板。每个星期都会往里补充一条新学到的东西。半年下来这个文件几乎成了我的PG速查手册。你自己也完全可以用同样的方式积累这篇文章里的所有命令都可以作为前一百条内容。2. 连接、建库与日常增删改查先把活干起来2.1 psql连接命令的完整参数与常见报错连接PG最基础的一条命令长这样psql -h 127.0.0.1 -p 5432 -U myuser -d mydb-h后面是数据库地址-p是端口-U是用户名-d是数据库名。不加-d的话PG会用你当前的操作系统用户名作为默认库名去连接经常报database xxx does not exist很多新手在这个报错上卡了很久实际上就是因为没指定库名。如果想要密码自动提示加一个-W参数。如果服务器配置了本地信任认证不需要密码那个别纠结。还有一点要注意psql的参数顺序是宽松的-d mydb -U myuser和-U myuser -d mydb完全等价这点比很多命令行工具友好。连接过程中常见的报错我整理了一下报错信息常见原因处理方向could not connect to server端口没通、防火墙拦截、服务没起来检查pg_isready、netstat、防火墙database xxx does not exist没指定-d或库名拼错确认库名或用\l查看password authentication failed密码错误、认证方式不是md5/scram检查pg_hba.conf认证方法no pg_hba.conf entry客户端IP不被允许在pg_hba.conf增加对应网段规则并reload以上这些报错文本虽然不是完整的原文但特征基本一致。遇到问题先看最后一行PG的错误信息其实写得很清楚只是很多人喜欢忽略英文直接抄日志问别人。连接成功以后psql提示符会变成mydb#或者mydb。前者代表你有超级用户权限后者代表普通用户。这个细微差别其实很重要看到你就该意识到很多管理命令会执行失败。连上以后第一时间做的事我建议执行两条SELECT version(); SELECT current_database(), current_user, inet_server_addr();这两条可以确认你连到了哪个版本、哪个库、哪个用户、哪台服务器。特别是多环境混用的时候这个操作能救你一条命。2.2 创建库与表结构的常用SQL创建一个数据库SQL方式CREATE DATABASE mydb ENCODING UTF8;也可以在shell里直接createdb -h 127.0.0.1 -U myuser mydb删除数据库DROP DATABASE mydb;删除之前建议先确认没有连接占用否则会报being accessed by other users。我遇到过好几次开发环境里一堆IDEA的数据库面板自动挂着连接DROP DATABASE怎么都执行不了最后是把那些连接断开才成功。建表就没什么特异功能了CREATE TABLE requests ( id BIGSERIAL PRIMARY KEY, user_id INT NOT NULL, api_path TEXT NOT NULL, status_code INT DEFAULT 200, created_at TIMESTAMPTZ DEFAULT now() );BIGSERIAL是PG里常用的自增方式底层是一个序列。也可以直接用GENERATED AS IDENTITY这是SQL标准做法PG 12以后都支持得不错。二者差别不是很大但新项目我个人更推荐GENERATED AS IDENTITY语义更清晰也更方便后续迁移。查看表结构psql里直接\d requests它会显示每个字段的类型、默认值、约束还会列出索引、外键、触发器等附属结构比写SQL查information_schema快得多。想看到更细的存储属性用\d requests2.3 psql里高频元命令速查连接数据库这个动作在psql里用\c\c otherdb切换用户/库/端口也可以一步到位\c mydb myuser 127.0.0.1 5432列出所有数据库用\l列出当前库所有表用\dt想带上表注释和大小用\dt。看一个查询结果如果列太多被截断先开启扩展显示\x on开启后每一行字段会竖着排同一条SQL再执行一遍就清爽很多。这个模式在排查问题时几乎是必开的。日常写SQL的时候我很依赖两个元命令\timing on \e\timing会打印每次SQL的执行耗时不用自己手动记秒表。\e会打开默认编辑器通常是vi适合写多行SQL写完退出自动执行。在有临时复杂查询的场景下这个组合比一条条敲要舒服太多。执行外部SQL脚本用\i\i /path/to/script.sql导出查询结果到文件在psql里可以用\o或者直接在shell里重定向psql -U myuser -d mydb -c SELECT * FROM requests; output.csv3. 信息查询命令排查问题时的救火地图日常运维中你真正需要手写SQL去查的地方集中在几个系统视图和统计视图里。这一节的内容可以说是PG数据库相关命令里最有价值的部分因为大部分故障的第一现场都是从这里找到的。3.1 pg_catalog 与 information_schema 的选择PG里有两个元数据来源information_schema是SQL标准视图跨数据库通用pg_catalog是PG自身系统表视图信息更全更底层。查询表结构、列名、约束这类通用信息用information_schema比较稳。但查询物理存储、膨胀情况、逻辑复制状态这些PG特性信息必须用pg_catalog下的视图比如pg_class、pg_namespace、pg_attribute、pg_stat_activity等。从使用频率来看我80%的查询都在pg_catalog体系里。information_schema更多是给报表系统或者图形化工具用的标准化接口。查看一个库下所有表和对应的注释SELECT c.relname AS table_name, obj_description(c.oid) AS comment FROM pg_class c JOIN pg_namespace n ON n.oid c.relnamespace WHERE n.nspname public AND c.relkind IN (r, p) ORDER BY c.relname;这个查询虽然啰嗦但理解了pg_class和pg_namespace之后PG的系统表结构就通了一半。3.2 当前连接、锁等待与活动查询排查数据库突然变慢最常用的视图绝对是pg_stat_activity。一条查询跑遍所有问题SELECT pid, usename, datname, client_addr, state, wait_event_type, wait_event, query_start, now() - query_start AS runtime, query FROM pg_stat_activity WHERE state ! idle ORDER BY runtime DESC;看到state字段是active的进程结合query_start算一下运行时长基本就能判断是正常慢查询还是异常堵塞。如果大量会话卡在某个状态且wait_event带有Lock字眼说明存在锁等待。锁定位到具体是哪个进程堵了之后可以用这个函数查链条SELECT pg_blocking_pids(4567);把4567替换成你看到的被阻塞pid返回的结果就是堵住它的pid列表。然后再连查一层直到源头。终止一个会话SELECT pg_cancel_backend(4567);取消不掉就用SELECT pg_terminate_backend(4567);两者的区别是cancel是温和取消当前查询事务本身可以被应用捕获错误后回滚比较适合对付慢查询terminate是直接断开进程会把整个客户端连接杀掉适合对付僵死连接。生产环境用terminate之前最好先确认这个连接是谁的、能不能断。3.3 表大小、膨胀与索引使用统计磁盘空间到底被哪些表吃掉了很多人第一反应是去看文件目录其实一条SQL就出来了SELECT nspname || . || relname AS relation, pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size, pg_size_pretty(pg_relation_size(c.oid)) AS table_size, pg_size_pretty(pg_total_relation_size(c.oid) - pg_relation_size(c.oid)) AS index_size FROM pg_class c JOIN pg_namespace n ON n.oid c.relnamespace WHERE c.relkind r AND n.nspname public ORDER BY pg_total_relation_size(c.oid) DESC LIMIT 20;pg_size_pretty会把字节数换算成人类的可读格式这个函数在你处理空间问题时是高频使用的。检查表的膨胀情况看pg_stat_user_tablesSELECT relname, n_live_tup, n_dead_tup, CASE WHEN n_live_tup 0 THEN round(100.0 * n_dead_tup / n_live_tup, 1) ELSE 0 END AS dead_pct, last_vacuum, last_autovacuum FROM pg_stat_user_tables ORDER BY dead_pct DESC LIMIT 20;n_dead_tup代表死元组数量这个值长期偏高说明vacuum没跟上表膨胀风险很高。索引命中率查询SELECT schemaname, relname, indexrelname, idx_scan, idx_tup_read, pg_size_pretty(pg_relation_size(indexrelname)) AS index_size FROM pg_stat_user_indexes ORDER BY idx_scan ASC LIMIT 20;idx_scan长期为0的索引基本可以视为无效索引但注意先确认没有唯一性约束不能只看使用率就删。这类统计视图是PG排查性能问题时最重要的地图把它们当成常备工具胜过去背各种优化口诀。4. 备份与恢复生产环境最常翻车的命令组合备份恢复这块网上教程不少但大多数人只讲了pg_dump一条命令。这里我重点讲的是命令怎么组合、恢复到另一个环境时有哪些隐藏的坑这些才是生产环境真正要命的东西。4.1 pg_dump的格式选择与并行参数pg_dump最基础的用法pg_dump -h 127.0.0.1 -p 5432 -U myuser -d mydb -f mydb.sql这会生成一个纯SQL文本文件里面是建表语句和数据插入语句。这种格式最大的好处是人眼可读适合小库、跨小版本迁移。但大库用纯SQL恢复特别慢并且中途出错很难续跑。我更推荐custom格式pg_dump -h 127.0.0.1 -U myuser -d mydb -F c -f mydb.dump-F c 生成的是一种压缩的二进制格式可以用pg_restore灵活控制恢复哪些对象。custom格式还支持并行恢复恢复大库时速度快非常多。并行恢复pg_restore -h 127.0.0.1 -U myuser -d targetdb -j 4 mydb.dump-j 4代表开4个并发任务恢复。任务数建议不超过CPU核心数两倍不然反而会因为资源竞争变慢。只备份数据不带表结构用pg_dump -a -F c -f data_only.dump只备份表结构不带数据用pg_dump -s -F c -f schema_only.dump这两种方式在给测试环境搭建、生成对照库时特别实用。4.2 pg_restore与psql回放的核心逻辑说清楚一个问题custom格式不能用psql直接回放必须用pg_restore。这是很多新手卡住的点。拿个大半天研究为什么psql读dump文件报错其实只是格式选错了。一个常规的恢复流程# 先建目标库如果还不存在 createdb -U myuser -h 127.0.0.1 targetdb # 恢复custom格式备份 pg_restore -h 127.0.0.1 -U myuser -d targetdb -j 4 mydb.dump如果dump里包含了建库语句你可以用--create选项让它先建库再连库恢复但前提是执行pg_restore的用户必须有建库权限。查看一个dump文件里都包含了什么对象不用恢复就能列出pg_restore -l mydb.dump这个列表输出很长可以配合grep只看某类对象比如只看函数pg_restore -l mydb.dump | grep FUNCTION如果你只想恢复其中一张表pg_restore -t public.requests -d targetdb mydb.dump4.3 恢复翻车现场权限、扩展、版本三大坑我实际在恢复dump到测试环境时遇到最多的问题归纳成三个。第一个坑是owner不一致。原库的对象owner是prod_user目标环境里根本没有这个用户恢复时直接报错。解决办法是加上--no-ownerpg_restore --no-owner -d targetdb mydb.dump这个选项让恢复后的对象owner统一变成当前执行用户规避掉一大部分权限问题。第二个坑是扩展缺依赖。比如表里有jsonb字段或者用了citext类型恢复时目标库没安装对应扩展就会报type does not exist。普通文本格式的dump里如果包含CREATE EXTENSION需要执行者具有超级用户权限否则也会被跳过。恢复之前先把该装的核心扩展装上CREATE EXTENSION IF NOT EXISTS citext; CREATE EXTENSION IF NOT EXISTS uuid-ossp;第三个坑是版本跨度过大。PG大版本之间的二进制格式不兼容pg_dump出来的dump文件最好在大版本内恢复。跨大版本迁移建议先用低版本自带的pg_dump导出再到高版本用pg_restore导入方向不能反。高版本导出的文件去低版本恢复基本都会失败。还有一个很实用的细节给备份文件做完整性校验恢复完以后立刻跑一遍行数抽查SELECT COUNT(*) FROM public.requests;这个动作成本不高但能快速发现数据中途丢失。5. 权限与角色命令从能跑到管得住数据库能在本地跑起来和能在生产环境管得住之间的分界线就是权限命令。PG的权限体系比MySQL更细致但也因此容易踩到一些给了权限却还是报错的坑。5.1 角色与用户的本质区别在PG里角色ROLE和用户USER本质上是同一个东西。CREATE USER只是CREATE ROLE的一个便捷写法区别仅在CREATE USER会默认带着LOGIN属性而CREATE ROLE默认不带。CREATE ROLE app_user LOGIN PASSWORD xxx;等价于CREATE USER app_user PASSWORD xxx;查看当前实例下所有角色\du这个命令会列出角色名、属性列表和成员关系一屏看全好人坏人。改密码ALTER ROLE app_user WITH PASSWORD newpassword;角色继承关系CREATE ROLE read_only; GRANT read_only TO app_user;app_user登录后默认继承read_only的权限。PG的权限检查加上继承特性理解起来需要一点叠加思维但实际使用中用继承方式管理是很优雅的。5.2 一组可以直接照抄的授权模板我根据实际场景整理了三个常用模板你可以直接搬走用。给一个只读账号CREATE ROLE read_only LOGIN PASSWORD xxx; GRANT CONNECT ON DATABASE mydb TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO read_only;注意这里GRANT CONNECT是让你能连上这个库GRANT USAGE ON SCHEMA是让你能看到并使用这个schema下的对象。很多人只记得给表授权忘了给schema授权结果用户连上库之后一执行SELECT就报permission denied for schema public。给一个读写账号CREATE ROLE read_write LOGIN PASSWORD xxx; GRANT CONNECT ON DATABASE mydb TO read_write; GRANT USAGE, CREATE ON SCHEMA public TO read_write; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO read_write; GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO read_write; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO read_write; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE ON SEQUENCES TO read_write;ALTER DEFAULT PRIVILEGES这段很多新手会忽略它的作用是以后在这个schema里新建的表默认自动授权给指定角色。不加这个今天你给用户授了权明天业务方新加了一张表用户又查不了看起来就是权限神秘失效。只读账号顺便给序列的usage是因为如果查询要走某些带序列的视图或函数可能会被卡住。实际场景中遇到这类报错就明白了。查看某个表当前权限用\dp tablename或者SELECT grantee, privilege_type FROM information_schema.role_table_grants WHERE table_name tablename;5.3 权限问题上最容易忽略的三个场景第一个场景前面提到过的schema权限。很多团队在给一个新账号授权时列了一长串表自认为都覆盖了结果用户一登录就报permission denied。问题不在表上而是USAGE ON SCHEMA没给。这就像你给了别人一把房间钥匙却不让对方进走廊。第二个场景函数执行权限。PG里函数默认为PUBLIC可执行但如果你在函数内部访问了其他表这个用户必须同时拥有那些表的权限否则调用函数时依然会被拒绝。这个报错藏得比较深往往不是在授权时发现而是应用跑到一半才炸。第三个场景REVOKE之后还有残留。想彻底收回一个用户对某张表的所有权限不能只REVOKE一次需要把SELECT、INSERT、UPDATE、DELETE、TRUNCATE、REFERENCES、TRIGGER全部回收REVOKE ALL PRIVILEGES ON TABLE public.requests FROM app_user;REVOKE ALL这种写法一次清干净不要分开写。6. 性能诊断命令EXPLAIN、慢SQL与锁等待性能诊断这一块是你把PG从能跑带到跑得快的核心。我会先把EXPLAIN怎么读讲透再说慢SQL定位三板斧最后说锁等待处置。6.1 EXPLAIN ANALYZE到底怎么读写SQL的时候如果怀疑查询慢直接在SQL前面加EXPLAIN ANALYZE比如EXPLAIN ANALYZE SELECT u.name, count(*) FROM requests r JOIN users u ON u.id r.user_id WHERE r.created_at now() - interval 7 days GROUP BY u.name;输出会是一棵执行计划树从缩进最深的节点开始看每一行都有三个关键数字actual time、rows、actual loops。actual time字段的第一个数字是启动时间获得第一行前的耗时第二个数字是整个过程耗时单位毫秒rows是实际扫描的行数要和EXPLAIN里预估的行数对比rows大比例偏差说明统计信息失效需要ANALYZE或者检查索引判断执行计划好坏最简单的方法是找两个词Seq Scan和Index Scan。看到Seq Scan在表上扫了几十万行而你还期望它走索引那基本就是索引缺失、统计信息过期、或者SQL写得让优化器没法用索引。看一个例子上面SQL如果输出里显示requests表做了Seq Scan且扫描了50万行user表也做了Seq Scan那这个查询大概率会慢。解决办法一般是在requests.user_id和requests.created_at上建复合索引并确保统计信息是最新的。加索引的命令CREATE INDEX CONCURRENTLY idx_requests_user_created ON public.requests (user_id, created_at DESC);CONCURRENTLY关键字表示不阻塞写操作。生产环境建索引时我强烈建议不要省略它虽然它会让索引创建更慢且不能在事务里执行但换来的是不打断应用写入值得。6.2 慢SQL定位三板斧第一板斧是看pg_stat_activity找到正在跑的query和运行时长。这个前面已经给过SQL区别是要记住它只看得到正在执行的历史慢SQL它不会记录。第二板斧是安装pg_stat_statements扩展。这个扩展是慢SQL统计的利器CREATE EXTENSION IF NOT EXISTS pg_stat_statements;安装之后可能需要数据库管理员在配置里先开启shared_preload_libraries并重启实例默认情况下有些环境已经预加载了直接查询即可。查询执行总次数多、总耗时长、平均耗时长的SQLSELECT queryid, calls, round(mean_exec_time::numeric, 2) AS avg_ms, round(total_exec_time::numeric, 2) AS total_ms, round(max_exec_time::numeric, 2) AS max_ms, query FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 20;这个查询会告诉你过去这段时间里到底哪几条SQL在燃烧你的数据库CPU和IO。有几次线上事故最终定位到源头就是pg_stat_statements里某条应用生成的动态SQL没有用上索引。第三板斧是开慢查询日志。修改配置ALTER SYSTEM SET log_min_duration_statement 1000; SELECT pg_reload_conf();意思是执行超过1000毫秒的SQL都会写入日志文件。这个参数在生产环境非常有用改完后不用重启reload即可生效。6.3 锁等待的定位与处置命令锁等待和慢查询经常伴生不是SQL本身慢而是卡在等锁。定位步骤通常这样走。第一步看pg_stat_activity里wait_event有没有Lock字样SELECT pid, state, wait_event_type, wait_event, query_start, query FROM pg_stat_activity WHERE wait_event_type Lock;第二步用pg_blocking_pids找到锁源SELECT pid, pg_blocking_pids(pid), query FROM pg_stat_activity WHERE wait_event_type Lock;第三步定位到源头会话后用前面说过的pg_cancel_backend或者pg_terminate_backend处理。这里想特别提醒一件事lock_timeout这个参数值得在设计表结构时就考虑。在长时间持锁的DDL场景下给应用会话设置SET lock_timeout 5s;可以让等待锁的会话在5秒后自动放弃而不是无限期挂在那里。很多数据库无响应事故就是被无限等锁拖死的。7. 维护类命令避坑清单日常运维绕不开的几件事最后这部分讲几个日常维护中绕不开的命令每个命令都有它典型的为什么和别乱动。7.1 VACUUM、ANALYZE与膨胀处理PG的并发控制靠MVCC删除一行数据并不会立刻从物理文件里抹掉而是标记为死元组。这些死元组要靠VACUUM清理。VACUUM public.requests; VACUUM ANALYZE public.requests;普通VACUUM不锁表可以在线跑。ANALYZE会更新统计信息优化器等会儿执行计划就能更准确。两者一起跑是常规操作。生产环境其实不必频繁手动执行因为PG默认开着autovacuum。但对一些超大表autovacuum可能来不及清理这时候可以在业务低谷手动跑一次。千万注意不要轻易在生产环境用VACUUM FULLVACUUM FULL public.requests;VACUUM FULL会重写整张表并且全程持锁大表跑起来期间应用写入全部阻塞。我见过有人因为一张几亿行的表膨胀严重直接在高峰时段执行VACUUM FULL结果整个业务停摆。正确的思路是优先确认autovacuum配置正常实在需要物理收缩时才考虑VACUUM FULL而且放在维护窗口执行或者直接通过新表迁移来替代。7.2 配置修改与生效方式ALTER SYSTEM与reload修改PG配置不建议直接去编辑postgresql.conf因为容易出错。PG 9.4以后支持ALTER SYSTEMALTER SYSTEM SET max_connections 500;修改完后一部分参数需要reload生效SELECT pg_reload_conf();还有一部分参数必须重启实例才生效。重要参数大致可以分两类参数是否需要重启典型场景max_connections重启连接数不足shared_buffers重启内存缓冲不足work_mem无需会话级生效排序/哈希操作慢log_min_duration_statement无需reload慢SQL追踪effective_cache_size无需reload优化器选错计划work_mem有个坑值得单独说它表示单个排序或哈希操作能使用的内存不是整个查询。如果你把它设置成1GB而并发50个会话都在排序瞬间就能吃掉50GB内存。所以修改这类参数要结合并发量不能只看单次操作。7.3 连接数打满时的急救流程连接数打满是一种特别常见的故障表现为新连接报too many connections。急救步骤一般是这样第一步看当前连接分布SELECT datname, usename, count(*) FROM pg_stat_activity GROUP BY datname, usename ORDER BY count(*) DESC;第二步杀掉明显异常的连接。如果是一些应用的重试连接堆积可以用pg_terminate_backend批量清理掉非关键连接。谨慎一点的做法是先把它们cancel了再看。第三步调整连接池的配置。生产环境应用不应该直连PG中间一定套一个连接池应用层控制连接池上限PG端用pgbouncer或者proxysql做集中池化。如果没接连接池max_connections再大也只是慢性死亡。这个属于架构问题但和命令使用的关联很深。另一个维护命令是CHECKPOINTCHECKPOINT;它作用是把WAL缓冲区的内容刷到数据文件让崩溃恢复更快。平时不需要手动执行但如果在做某些备份或要关闭实例之前执行一次可以缩短恢复时间。这也算是我见过的命令存在但很少被正确使用的一类。最后说个经验这篇文章列的命令我在真实项目里都实际用过。如果你现在刚起步我的建议是先别急着把每条命令背下来动手执行一遍然后按自己的使用场景把这个速查文档沉淀下来。把五个场景练熟就够了连接、查询信息、备份恢复、权限、慢查询排查。等这五块熟了剩下的都是随用随查。另外想强调一个总的习惯凡是涉及生产环境的命令先在一个空库里试一遍。特别是DROP、TRUNCATE、VACUUM FULL这类重量级操作试完你才会对它的输出和影响有切身体感。数据库命令的价值不在知道而在用对。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑