你平时用数据库的时候,好像一切都挺简单:加一行、改个记录、删个客户。但其实这背后有一套很复杂、很精妙的机制。那些数据到底存哪儿了?为啥 PostgreSQL 就算服务器突然断电也不会丢数据?
想搞明白这些,你得知道两件事:数据(表、索引、服务信息)到底物理上放哪儿,以及数据保护机制是怎么搞的——也就是事务日志,WAL(Write-Ahead Logging)。
整个 PostgreSQL 数据库其实就是一堆文件,放在一个专门的目录里——data_directory。一般都在这儿:
/var/lib/postgresql/17/main
这个文件夹就是数据库的心脏:表、索引、元信息、配置全都在这儿。WAL 日志也在这里——它是第一个接收所有变更的机制。数据还没真正写进表文件前,都会先写进 WAL。就像草稿本,数据库把每一步都记下来,这样哪怕出事了,也能恢复到最后一次操作。
靠这种方式,PostgreSQL 就算在最不靠谱的环境下也能保证数据安全和稳定。
表
每个表其实就是一个独立的文件或者一组文件。这些文件都在 base/ 子目录下。结构大概这样:
$PGDATA/base/
├── 16384/
│ ├── 12345 ← 表
│ ├── 12346 ← 索引
│ └── ...
16384—— 这是数据库的内部 ID(OID)。12345—— 这是具体表的 ID。
如果表很大,PostgreSQL 会把它按 1GB 分成多个段:
12345
12345.1
12345.2
...
这些文件里可不是像 CSV 那样的“行”,而是 8KB 的“二进制页面”格式。
WAL: Write-Ahead Logging —— 不只是个“日志”
现在说说 PostgreSQL 里最重要、但经常被误解的部分之一——WAL,也就是Write-Ahead Logging。别看名字里有 log,WAL 可不是普通的文本日志文件,不像错误日志或者查询日志那样。它是保证数据一致性和恢复的核心机制,直接操作底层文件系统的变更。
WAL 不是事件报告,而是所有即将发生的数据变更的预写记录。而且这记录是在真正改表文件之前写进去的。所以才叫 write-ahead ——“提前写”。
比如你往表里插一行,PostgreSQL 会:
- 不会立刻改表文件 —— 这样又慢又不安全。
- 先写进 WAL,说明要加这一行。
- 等到合适的时候(比如后台进程),才真的把数据写进表文件。
这就像你在银行开支票:先签个支票(WAL),银行之后才会更新账户(表)。要是出点啥事——支票还在手上,操作还能重来。
WAL 的格式和结构
- WAL 文件是二进制格式的。
- 每个文件都是严格有序的操作流,描述了数据页、索引结构、提交等的内部变更。
- 一个 WAL 文件大小是固定的——默认 16MB。
注意:WAL 里没有“SQL 命令”或者“表的行”这种东西。它只存PostgreSQL 引擎用来重放变更的指令,一页一页地还原。
崩溃时会发生什么?
如果 PostgreSQL 服务器突然挂了——比如断电——也不用慌。下次启动时,数据库不会慌张,而是先从磁盘加载最后一次保存的“稳定”数据版本。然后它会拿出事务日志(WAL),把里面还没写进主文件的所有变更都“补上”。这样数据库就能恢复到完全一致的状态,仿佛啥事都没发生。
WAL 的额外功能
Point-In-Time Recovery (PITR)。 只要保存 WAL 文件,就能把数据库恢复到任意时间点,只要在两个完整备份之间。
流式复制。 PostgreSQL 可以实时把 WAL 记录发到另一个服务器。这就能搞热备份——和主库同步的数据库副本。
增量恢复。 配合完整备份,WAL 能只恢复变更的部分,不用全库重拷贝。
做二进制备份:pg_basebackup
如果你用过 pg_dump,就知道它很适合做逻辑备份(把数据库结构和数据导成 SQL 语句)。但要是你想做物理备份呢?比如把数据库所有文件完整镜像一份?这时候就要用 pg_basebackup 了。
pg_basebackup 是个能做 PostgreSQL 物理拷贝的工具。它对大数据库特别有用,能高效管理恢复流程。最大优点就是速度快。
pg_basebackup 的基本命令用法
用 pg_basebackup,先得搞懂它的命令格式。在终端里执行,基本长这样:
pg_basebackup -D /backup_directory -F tar -z -P
来拆解一下:
-D /backup_directory—— 指定备份文件要存哪儿。-F tar—— 数据格式。tar选项会生成.tar格式的归档文件。你也可以用plain,那就是数据库文件夹结构。-z—— 压缩备份,省磁盘空间。谁不喜欢备份小点呢!-P—— 实时显示进度。看着进度条,心里更踏实:知道进程没卡死。
用法示例:
pg_basebackup -D /backups/university_backup -F tar -z -P
执行完后,在 /backups/university_backup 目录下就有了 .tar 格式的备份。
用 pg_basebackup 的好处
高效: 增量备份不会重复拷贝没变的数据,省时又省空间。
简单易用: pg_basebackup 自动处理所有细节,包括 WAL 文件。
靠谱: 跟 PostgreSQL 引擎深度集成,pg_basebackup 能做出完整可恢复的数据库副本。
使用示例
下面来点实操。这里有几个 pg_basebackup 的真实用法例子:怎么做基础备份、怎么加压缩、怎么开启 WAL 日志归档(这样就能恢复到任意时间点)。这些命令新手老手都能用。
做基础备份
pg_basebackup -D /backups/full_backup -F tar -z -P
结果:一个完整的数据库 .tar 归档备份。
设置压缩和格式
做个高压缩级别的备份:
pg_basebackup -D /backups/full_backup -F tar -z -Z 9 -P
这里 -Z 9 是压缩级别(最高 9)。
WAL 归档
如果你配置了 WAL 归档,数据库就能恢复到任意时间点。设置 WAL 备份的命令:
pg_basebackup -D /backups/incremental_backup -F tar -z -P --wal-method=archive
GO TO FULL VERSION