PostgreSQL 入门:与 MySQL 的心智差异

这篇要解决的问题

你用过 MySQL(或者只用过 MySQL),新项目、新团队或新岗位要求用 PostgreSQL(下文简称 PG)。这篇不打算把 PG 的功能从头罗列一遍,而是按”从 MySQL 迁移心智”的顺序讲四件事:装起来跑通、与 MySQL 的关键差异、database 与 schema 这层容易忽略的概念、以及 pg_dump 备份的最小可用姿势。看完的验收标准:本机有一个能连上的 PG 实例,建了一个专用的库和账号,并手工导出过一次备份。

安装与最小可用环境

先装再说。当前稳定大版本是 PostgreSQL 18(2025 年 9 月发布),17 仍在五年支持期内,每年会出一个新的大版本;安装命令不必钉版本号,发行版源里给哪个用哪个,项目里用什么版本以你的团队约定为准:

# Debian/Ubuntu:contrib 包里带常用扩展,建议一起装
sudo apt install postgresql postgresql-contrib

1. macOS(Homebrew),装完用服务方式启动
brew install postgresql@18
brew services start postgresql@18

1. 或者不想动本机环境,直接起一个容器
docker run --name pg-intro -e POSTGRES_PASSWORD=devpass -p 5432:5432 -d postgres

验证连接。PG 的交互客户端叫 psql,服务端控制工具叫 pg_ctl。发行版包安装时通常已经自动初始化数据目录并启动了服务,Docker 镜像的入口脚本也会代劳 initdb,所以新手阶段不用碰初始化命令,先建立”能连上、能建库”的手感:

psql -U postgres        # 进入交互终端,\q 退出
1. Docker 方式:docker exec -it pg-intro psql -U postgres
-- psql 里以反斜杠开头的元命令不需要分号
\l                 -- 列出所有数据库
CREATE ROLE appuser LOGIN PASSWORD 'app_pass';  -- 先建角色(PG 里用户就是能登录的角色)
CREATE DATABASE appdb OWNER appuser;            -- 再建库,并指定属主
\c appdb appuser   -- 切换数据库和用户
\dt                -- 列出当前库的表
\d users           -- 看表结构,相当于 MySQL 的 SHOW CREATE TABLE 加 DESCRIBE

反模式点名:拿 postgres 超级用户当应用的连接账号。MySQL 时代很多人习惯 root 直连,这个习惯带到 PG 里,会让误操作的爆炸半径扩大到整个实例。正确做法是给每个应用建独立角色,只授予它自己那个库的权限。

与 MySQL 的五个心智差异

维度 MySQL 的行为 PostgreSQL 的行为 对你的影响
标识符大小写 表名大小写敏感与否取决于系统变量和操作系统(Linux 默认敏感),列名不敏感 不加引号的标识符一律折叠为小写,加双引号才保留大小写 跨库迁移最常见的意外来源;工具生成的带引号语句混用后,会出现”同名不同库”的两张表
DDL 与事务 DDL 隐式提交,无法回滚 CREATE/ALTER TABLE 是事务的一部分,可以随事务回滚 迁移脚本可以整体成败,不存在”改到一半”的中间态
MVCC 实现 旧版本写入 undo log,回滚段单独存放 旧版本元组留在表内,靠 autovacuum 后台回收 高频更新的表会膨胀,长事务会卡住回收,需要盯着膨胀率
JSON 能力 JSON 类型,支持函数与生成列索引 JSONB 二进制存储,GIN 索引,操作符覆盖面广 半结构化字段在 PG 里更”敢用”,但仍别把关系库当文档库
扩展生态 插件数量相对有限 CREATE EXTENSION 一行启用 PostGIS、pg_stat_statements、pgvector 等 PG 很多”杀手锏”来自扩展,装机时记得带上 contrib 包

其中两条值得展开。大小写折叠:MySQL 里 SELECT * FROM Users 和 users 在 Linux 上是两张不同的表,而 PG 里两者都是 users;反过来的坑是,PG 里建表时写了带引号的 "Users",之后所有查询都得永远带引号。建议团队约定:标识符一律小写加下划线,永远不加引号。

VACUUM:PG 的更新等于”插入新版本 + 标记旧版本死亡”,磁盘空间不会立刻释放。autovacuum 会自动回收,但它的触发节奏赶不上写入高峰时表就膨胀。日常只需要记住两件事:不要长时间挂着事务不提交;偶尔用 pg_stat_user_tables 看一眼死元组数量(慢查询膨胀的定位方法会在站内排障篇展开)。

database、schema 与 search_path

MySQL 的层级是”实例 > database > 表”。PG 多了一层:”实例 > database > schema > 表”。很多 MySQL 用户说的”建一个库”,在 PG 里更合适的对应物是建一个 schema,而不是建一个 database——因为 PG 的 database 之间完全隔离,跨库查询需要额外的外部数据包装器(FDW),而同一 database 内的多个 schema 之间查询毫无障碍。

每个新建的 database 默认有一个 public schema,不写前缀的表都落在 search_path 指定的第一个 schema 里。实践上常见的用法是按业务域或按租户拆 schema:billing.orders、crm.customers,权限可以按 schema 整体授予,比逐张表授权省事得多。

CREATE SCHEMA billing;
CREATE TABLE billing.orders (id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY);
GRANT USAGE ON SCHEMA billing TO appuser;   -- 按 schema 整体授权,而不是逐表
SET search_path TO billing, public;          -- 决定不带前缀的表名去哪找

pg_dump 备份一分钟上手

# 纯文本 SQL:人能读、能进版本库审阅,适合小库
pg_dump -U appuser appdb > appdb.sql

1. 自定义压缩格式:配合 pg_restore 支持并行恢复和选择性恢复,适合大库
pg_dump -U appuser -Fc appdb > appdb.dump

1. 对应的两种恢复方式
psql -U appuser -d appdb_restored < appdb.sql
pg_restore -U appuser -d appdb_restored -j 4 appdb.dump

两个容易忽略的点:pg_dump 不导出角色和表空间,整机迁移要配合 pg_dumpall --globals-only 把全局对象一起带走;恢复出来的库要重新 ANALYZE 一次,统计信息才齐全。定时备份用 cron 加时间戳文件名即可起步,但恢复演练比备份本身重要——没有恢复过的备份等于没有备份。

小结与边界

这篇走完了安装、五个心智差异、schema 概念和备份的最小闭环。诚实地说边界:如果团队只熟 MySQL、现有负载也用不到 JSONB、地理数据或 DDL 事务,没有必要为了”PG 更先进”而迁移,这些差异只有在你用得到时才是优势。反过来,要处理地理数据(PostGIS)、向量检索(pgvector)或者重分析负载,PG 基本就是默认答案。迁移决策看需求,不看社区声量。

延伸阅读:MySQL 侧的慢查询定位思路见《MySQL 慢查询定位与索引失效:从 slow log 到 EXPLAIN》;数据库在整体架构里的定位,可结合集群架构规划的思路理解;

版本核实(以官方文档为准):PostgreSQL 18 于 2025-09-25 发布,官方策略为约每年一个新的大版本、每个大版本支持五年;文中 psql 元命令、pg_dump/pg_restore、CREATE EXTENSION、schema 与 search_path 均为长期稳定特性,具体参数默认值以 postgresql.org 当前版本文档为准。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇