阅读视图

发现新文章,点击刷新页面。
🔲 ⭐

PostgreSQL 吞噬世界,MongoDB 起诉 Go 开源项目:2025 数据库年度盘点

本文永久链接 – https://tonybai.com/2026/01/08/databases-in-2025-a-year-in-review

大家好,我是Tony Bai。

数据库领域的“毒舌”,CMU教授 Andy Pavlo 再次发布了他的年度回顾(虽然这次是站在 2026 年初的回望)。2025 年对于数据基础设施是疯狂的一年:PostgreSQL 继续确立其霸主地位,引发了巨头间的收购狂潮;AI Agent 通过 MCP 协议正式接管数据库交互;而 Go 社区熟知的 FerretDB 则陷入了与 MongoDB 的法律泥潭。本文将为你深度梳理这份报告背后的技术趋势与行业信号。

img{512x368}

PostgreSQL 的统治:云巨头的“军备竞赛”

如果说 2021 年 Andy Pavlo 首次提出“PostgreSQL 正在吞噬数据库世界”,那么 2025 年则是这一预言的终极验证。PostgreSQL 不再仅仅是一个选项,它已经成为了行业标准,引发了云巨头之间近乎疯狂的并购与研发竞赛。

核心事件与技术演进

  • PostgreSQL v18 发布:终于引入了异步 I/O (Asynchronous I/O) 存储子系统,这意味着 Postgres 终于开始摆脱对操作系统页缓存(OS Page Cache)的依赖,向现代化 DBMS 架构迈出了关键一步。此外还增加了对 Skip Scans 的支持。
  • 天价收购案
    • Databricks 以 10 亿美元收购 Neon:Neon 是著名的“Serverless Postgres”开创者,其存算分离架构是现代云数据库的标杆。
    • Snowflake 以 2.5 亿美元收购 CrunchyData:为了不甘人后,Snowflake 也迅速补齐了其 Postgres 拼图。
    • Microsoft 发布 HorizonDB:作为回应,微软推出了自己的下一代 Postgres DBaaS。

对于后端和 Go 开发者而言,这意味着 PostgreSQL 协议已成为事实上的“通用语”。无论底层是 Aurora、AlloyDB 还是 Neon,应用层都只需通过标准的 pgx 或 lib/pq 驱动进行连接。掌握 Postgres 的深层特性和优化技巧,将成为未来五年内最具价值的技能之一。


MCP:AI Agent 时代的“中间件革命”

2025 年被定义为所有 DBMS 都支持 MCP (Model Context Protocol) 的一年。

什么是 MCP?

MCP 是由 Anthropic 提出,并随后被 OpenAI 采纳的一种标准化客户端-服务器 JSON-RPC 接口。它允许大语言模型(LLM)与外部工具和数据源进行交互,而无需编写定制的胶水代码。

  • 角色定位:MCP 服务器充当了数据库前的中间件。它向 LLM 暴露工具、数据和动作列表。
  • 工作流:LLM (MCP Client) -> MCP Server -> Database Query (SQL)。

Andy Pavlo 指出,除了官方实现外,还有数百个第三方的 MCP Server 实现。这对于 Go 开发者是一个巨大的机会:编写高性能、并发安全的 MCP 中间件是 Go 的拿手好戏

然而,这也带来了安全隐患。Pavlo 警告说,简单的代理只是将 MCP 请求翻译成 SQL,如果没有深度的内省和防护机制,AI Agent 可能会像“在应用里点了 18,000 杯水”一样,意外地摧毁数据库(比如 DROP DATABASE)。企业级 DBMS 开始内置 AI 防火墙,而开源生态则需要更多像 DBHub 这样提供查询限制和超时保护的中间件。


开源与法律:MongoDB v. FerretDB

这是 Go 社区最需要关注的法律纠纷。FerretDB 是一个用 Go 编写的开源项目,它提供了一个 MongoDB 兼容的代理层,后端使用 PostgreSQL 存储数据。这让用户可以用 Mongo 的驱动操作 Postgres。

诉讼焦点

  • 起因:MongoDB Inc. 向 FerretDB 发出停止侵权函,并在 2025 年 5 月正式提起联邦诉讼。
  • 指控:侵犯专利、版权、商标,以及违反 MongoDB 的文档和线协议规范的许可。MongoDB 特别针对 FerretDB 声称自己是“Drop-in replacement”(直接替换)这一点,认为其不仅误导开发者,还损害了 MongoDB 的声誉。
  • 背景:微软也将其 MongoDB 兼容的 DocumentDB 捐赠给了 Linux 基金会,但这似乎没有引发同样的法律反击,可能是因为巨头间的相互制衡。

警示

这一案件可能会成为 API 兼容性实现的法律判例。对于那些致力于编写“兼容层”或“协议转换器”的 Go 开发者来说,这是一个危险的信号:模仿专有软件的 API 和线协议,可能会面临越来越大的法律风险。


文件格式战争:Parquet 的挑战者们

在数据工程领域,Parquet 格式已经统治了近 15 年。但在 2025 年,为了适应现代硬件(NVMe SSD, GPU)和 AI 负载,新的挑战者涌现。

  • 挑战者联盟SpiralDB 的 Vortex(已捐赠给 Linux 基金会)、CWI 的 FastLanes、以及学术界的 F3 和 AnyBlox。
  • 核心痛点:现有的 Parquet 生态过于碎片化。Pavlo 的团队分析发现,94% 的 Parquet 文件仍在使用 2013 年的 v1 特性。
  • 未来趋势F3 格式(由 CMU, 清华大学等合作)提出了一种有趣的思路——在文件中嵌入 WASM (WebAssembly) 解码器。这意味着只要读取端支持 WASM,就可以解析任何自定义编码的数据,无需升级读取器本身。

行业大洗牌:并购与消亡

  • IBM 的野心:收购了 DataStax ($3B) 和 Confluent (Kafka 商业化公司),试图在数据流和 NoSQL 领域占据高地。
  • 向量数据库的退潮:随着所有主流 DBMS(Postgres, Oracle, Mongo)都内置了向量索引,单纯的“向量数据库”公司生存空间被挤压。Pinecone 正在寻求被收购,而 MyScaleDB 已经关闭。
  • GPU 数据库的黄昏Voltron Data 的倒闭和 HeavyDB 被 Nvidia 收购,似乎宣告了通用 GPU 数据库作为独立商业模式的终结。

总结与展望

Andy Pavlo 的这篇回顾虽然笔调幽默甚至带有讽刺,但其揭示的技术趋势却是严肃的:

  1. 架构趋同:存算分离、基于日志的架构(Log-based architecture)已成为云数据库的标配。
  2. AI 融合:数据库不再只是被动存储,而是通过 MCP 和内置向量能力,主动融入 AI Agent 的工作流。
  3. Go 的角色:在基础设施层(Docker/K8s 之后),Go 正在成为连接 AI 与数据的关键胶水语言(MCP Server, Proxy, 协议转换器)。

对于 Gopher 来说,关注 PostgreSQL 的协议生态、学习构建安全的 MCP 服务、并警惕开源协议的法律边界,将是 2025 年(及以后)的重要课题。

资料链接 – Databases in 2025: A Year in Review by Andy Pavlo


你的数据库“军火库”

数据库的世界正在发生剧变。在你的项目中,PostgreSQL 是否已经成为了默认选择?你如何看待 AI Agent 直接操作数据库的未来?

欢迎在评论区分享你的选型思考或对 FerretDB 事件的看法!让我们一起看清趋势,少走弯路。

如果这篇文章为你打开了数据库领域的新视野,别忘了点个【赞】和【在看】,并转发给你的架构师朋友!


还在为“复制粘贴喂AI”而烦恼?我的新专栏 AI原生开发工作流实战 将带你:

  • 告别低效,重塑开发范式
  • 驾驭AI Agent(Claude Code),实现工作流自动化
  • 从“AI使用者”进化为规范驱动开发的“工作流指挥家”

扫描下方二维码,开启你的AI原生开发之旅。


你的Go技能,是否也卡在了“熟练”到“精通”的瓶颈期?

  • 想写出更地道、更健壮的Go代码,却总在细节上踩坑?
  • 渴望提升软件设计能力,驾驭复杂Go项目却缺乏章法?
  • 想打造生产级的Go服务,却在工程化实践中屡屡受挫?

继《Go语言第一课》后,我的《Go语言进阶课》终于在极客时间与大家见面了!

我的全新极客时间专栏 《Tony Bai·Go语言进阶课》就是为这样的你量身打造!30+讲硬核内容,带你夯实语法认知,提升设计思维,锻造工程实践能力,更有实战项目串讲。

目标只有一个:助你完成从“Go熟练工”到“Go专家”的蜕变! 现在就加入,让你的Go技能再上一个新台阶!


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

© 2026, bigwhite. 版权所有.

🔲 ☆

PostgreSQL 使用全面指南:从入门到企业级应用

PostgreSQL 是世界上最先进的开源关系型数据库,以其强大的功能高度的扩展性严格的SQL标准兼容性著称。本教程将带你从基础到高级全面掌握PostgreSQL的使用技巧,涵盖安装配置、核心操作、高级特性和性能优化等各个方面。


一、PostgreSQL概述

PostgreSQL(常简称为Postgres)是一个功能强大的开源对象关系数据库系统,具有以下核心特点:

  • 高度符合SQL标准:支持SQL:2016标准的绝大部分功能
  • 可扩展性:支持自定义数据类型、函数、操作符和索引方法
  • ACID兼容:完全支持事务处理
  • 丰富的特性
  • 复杂查询
  • 外键
  • 触发器
  • 可更新的视图
  • 事务完整性
  • 多版本并发控制(MVCC)
  • 多语言支持:PL/pgSQL、PL/Python、PL/Perl、PL/Tcl等
  • 强大的扩展:PostGIS(地理空间)、pgRouting(路径规划)、TimescaleDB(时序数据)等
graph TD
PostgreSQL --> 核心功能[核心功能]
PostgreSQL --> 扩展模块[扩展模块]

核心功能 --> SQL标准
核心功能 --> ACID事务
核心功能 --> MVCC
核心功能 --> 复杂索引

扩展模块 --> PostGIS
扩展模块 --> TimescaleDB
扩展模块 --> pg_partman
扩展模块 --> PL/Python

二、安装与配置

不同平台安装

# Ubuntu/Debian
sudo apt update
sudo apt install postgresql postgresql-contrib

# CentOS/RHEL
sudo yum install postgresql-server postgresql-contrib
sudo postgresql-setup --initdb

# macOS (Homebrew)
brew install postgresql
brew services start postgresql

# Windows
下载安装包:https://www.postgresql.org/download/windows/

基本配置

  1. 初始化数据库集群
sudo -u postgres initdb -D /var/lib/postgres/data
  1. 启动服务
sudo systemctl start postgresql
sudo systemctl enable postgresql
  1. 配置访问权限
    编辑 pg_hba.conf
# 允许本地所有连接
localallalltrust
# 允许网络连接
hostallall0.0.0.0/0md5
  1. 修改监听地址
    编辑 postgresql.conf
listen_addresses = '*'

创建用户和数据库

-- 连接PostgreSQL
sudo -u postgres psql

-- 创建用户
CREATE USER myuser WITH PASSWORD 'securepassword';

-- 创建数据库
CREATE DATABASE mydb OWNER myuser;

-- 授予权限
GRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;

三、数据库基础操作

表操作

-- 创建表
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE,
department VARCHAR(50),
salary NUMERIC(10,2),
hire_date DATE DEFAULT CURRENT_DATE,
skills TEXT[]
);

-- 修改表
ALTER TABLE employees ADD COLUMN phone VARCHAR(15);
ALTER TABLE employees ALTER COLUMN department SET NOT NULL;

-- 删除表
DROP TABLE IF EXISTS temp_employees;

数据操作(CRUD)

-- 插入数据
INSERT INTO employees (name, email, department, salary)
VALUES
('张伟', 'zhang@company.com', '研发部', 15000),
('李娜', 'li@company.com', '市场部', 12000);

-- 查询数据
SELECT * FROM employees WHERE department = '研发部' AND salary > 13000;

-- 更新数据
UPDATE employees SET salary = salary * 1.1 WHERE department = '研发部';

-- 删除数据
DELETE FROM employees WHERE id = 5;

事务管理

BEGIN;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- 提交事务
COMMIT;

-- 出错时回滚
ROLLBACK;

四、数据类型详解

PostgreSQL提供丰富的数据类型:

类别 数据类型 描述
数值 SMALLINT, INTEGER, BIGINT 整数类型
NUMERIC(precision, scale) 精确小数
REAL, DOUBLE PRECISION 浮点数
字符 VARCHAR(n), TEXT 变长字符串
CHAR(n) 定长字符串
日期/时间 DATE, TIME, TIMESTAMP 日期时间类型
布尔 BOOLEAN true/false
二进制 BYTEA 二进制数据
几何 POINT, LINE, CIRCLE 几何图形
网络 INET, CIDR, MACADDR 网络地址
JSON JSON, JSONB JSON数据
数组 INT[], TEXT[] 数组类型
范围 INT4RANGE, TSRANGE 范围类型

JSONB示例

CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
attributes JSONB
);

INSERT INTO products (name, attributes)
VALUES ('Laptop', '{"color": "silver", "memory": "16GB", "ports": ["USB-C", "HDMI"]}');

-- 查询JSON字段
SELECT name, attributes->>'color' AS color
FROM products
WHERE attributes @> '{"memory": "16GB"}';

五、高级查询技术

窗口函数

SELECT
name,
department,
salary,
AVG(salary) OVER (PARTITION BY department) AS avg_dept_salary,
RANK() OVER (ORDER BY salary DESC) AS salary_rank
FROM employees;

CTE(公共表表达式)

WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales
FROM orders
GROUP BY region
),
top_regions AS (
SELECT region
FROM regional_sales
WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
)
SELECT region, product, SUM(quantity) AS product_units
FROM orders
WHERE region IN (SELECT region FROM top_regions)
GROUP BY region, product;

全文搜索

-- 创建全文搜索索引
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT,
body TEXT
);

CREATE INDEX idx_documents_search ON documents USING GIN (to_tsvector('english', body));

-- 执行搜索
SELECT title, ts_headline(body, q) AS highlight
FROM documents, to_tsquery('english', 'database & performance') q
WHERE to_tsvector('english', body) @@ q;

六、索引与性能优化

索引类型

索引类型 适用场景 示例
B-tree 默认索引,适用于等值查询和范围查询 CREATE INDEX idx_name ON table (column)
Hash 等值查询(仅内存表) CREATE INDEX idx_name ON table USING HASH (column)
GIN JSONB、数组、全文搜索 CREATE INDEX idx_gin ON table USING GIN (jsonb_column)
GiST 几何数据、全文搜索 CREATE INDEX idx_gist ON table USING GiST (geom_column)
SP-GiST 空间分区数据 CREATE INDEX idx_spgist ON table USING SP-GiST (phone)
BRIN 大型表,按物理顺序存储 CREATE INDEX idx_brin ON table USING BRIN (timestamp)

查询优化技巧

  1. 使用EXPLAIN分析
EXPLAIN ANALYZE SELECT * FROM large_table WHERE category_id = 10;
  1. **避免SELECT ***
-- 不推荐
SELECT * FROM orders;

-- 推荐
SELECT order_id, customer_id, order_date FROM orders;
  1. 批量操作优化
-- 使用COPY导入数据
COPY large_table FROM '/path/to/data.csv' DELIMITER ',' CSV HEADER;
  1. 分区表
-- 创建分区表
CREATE TABLE sales (
id SERIAL,
sale_date DATE,
amount NUMERIC
) PARTITION BY RANGE (sale_date);

-- 创建子分区
CREATE TABLE sales_2023 PARTITION OF sales
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');

七、事务与并发控制

事务隔离级别

-- 查看当前隔离级别
SHOW default_transaction_isolation;

-- 设置隔离级别
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

锁机制

-- 显式锁定
BEGIN;
LOCK TABLE accounts IN EXCLUSIVE MODE;
-- 执行操作
COMMIT;

-- 行级锁
SELECT * FROM orders WHERE id = 100 FOR UPDATE;

MVCC(多版本并发控制)

PostgreSQL使用MVCC处理并发,避免读写冲突:

stateDiagram-v2
[*] --> Active
Active --> Committed
Active --> Aborted
Committed --> [*]
Aborted --> [*]

八、存储过程与函数

PL/pgSQL函数

CREATE OR REPLACE FUNCTION calculate_tax(amount NUMERIC)
RETURNS NUMERIC AS $$
DECLARE
tax_rate NUMERIC := 0.1;
tax_amount NUMERIC;
BEGIN
tax_amount := amount * tax_rate;
RETURN tax_amount;
EXCEPTION
WHEN division_by_zero THEN
RAISE NOTICE 'Division by zero occurred';
RETURN 0;
END;
$$ LANGUAGE plpgsql;

-- 调用函数
SELECT calculate_tax(1000);-- 返回100.00

返回结果集

CREATE OR REPLACE FUNCTION get_employees(dept_name VARCHAR)
RETURNS TABLE (id INT, name VARCHAR, salary NUMERIC) AS $$
BEGIN
RETURN QUERY
SELECT e.id, e.name, e.salary
FROM employees e
WHERE e.department = dept_name;
END;
$$ LANGUAGE plpgsql;

-- 调用
SELECT * FROM get_employees('研发部');

九、触发器与规则

创建触发器

-- 审计日志表
CREATE TABLE audit_log (
id SERIAL PRIMARY KEY,
table_name VARCHAR(100),
action VARCHAR(10),
old_data JSONB,
new_data JSONB,
change_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 触发器函数
CREATE OR REPLACE FUNCTION log_employee_changes()
RETURNS TRIGGER AS $$
BEGIN
IF (TG_OP = 'DELETE') THEN
INSERT INTO audit_log (table_name, action, old_data)
VALUES (TG_TABLE_NAME, 'DELETE', to_jsonb(OLD));
ELSIF (TG_OP = 'UPDATE') THEN
INSERT INTO audit_log (table_name, action, old_data, new_data)
VALUES (TG_TABLE_NAME, 'UPDATE', to_jsonb(OLD), to_jsonb(NEW));
ELSIF (TG_OP = 'INSERT') THEN
INSERT INTO audit_log (table_name, action, new_data)
VALUES (TG_TABLE_NAME, 'INSERT', to_jsonb(NEW));
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 创建触发器
CREATE TRIGGER employees_audit
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW EXECUTE FUNCTION log_employee_changes();

十、备份与恢复

逻辑备份(pg_dump)

# 备份单个数据库
pg_dump -U username -d dbname -f backup.sql

# 备份所有数据库
pg_dumpall -U postgres -f alldb.sql

# 压缩备份
pg_dump -U username -d dbname | gzip > backup.gz

物理备份(PITR)

# 开启WAL归档
# postgresql.conf中设置:
wal_level = replica
archive_mode = on
archive_command = 'cp %p /path/to/wal_archive/%f'

# 创建基础备份
pg_basebackup -D /path/to/backup -U replicator -P -Fp -Xs -R

恢复数据库

# 从逻辑备份恢复
psql -U postgres -d newdb -f backup.sql

# 时间点恢复(PITR)
1. 恢复基础备份
2. 创建recovery.conf文件:
restore_command = 'cp /path/to/wal_archive/%f %p'
recovery_target_time = '2023-05-01 12:00:00'
3. 启动PostgreSQL

十一、高可用与复制

流复制配置

# 主库配置 (postgresql.conf)
wal_level = replica
max_wal_senders = 10
hot_standby = on

# 创建复制用户
CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'replpass';

# 备库配置
pg_basebackup -h master-host -U replicator -D /var/lib/postgres/data -P -Xs -R

# 备库postgresql.auto.conf中自动生成:
primary_conninfo = 'host=master-host user=replicator password=replpass'

使用pgPool-II负载均衡

# 安装pgpool-II
sudo apt install pgpool2

# 配置/etc/pgpool2/pgpool.conf
backend_hostname0 = 'master-host'
backend_port0 = 5432
backend_weight0 = 1
backend_hostname1 = 'replica1-host'
backend_port1 = 5432
backend_weight1 = 1

# 启动pgpool
systemctl start pgpool

十二、Python集成

import psycopg2
from psycopg2 import sql

# 连接数据库
conn = psycopg2.connect(
dbname="mydb",
user="myuser",
password="mypassword",
host="localhost",
port="5432"
)

try:
# 创建游标
with conn.cursor() as cursor:
# 执行查询
cursor.execute("SELECT * FROM employees WHERE department = %s", ('研发部',))
for record in cursor.fetchall():
print(f"ID: {record[0]}, Name: {record[1]}, Salary: {record[4]}")

# 插入数据
insert_query = sql.SQL("""
INSERT INTO employees (name, email, department, salary)
VALUES (%s, %s, %s, %s)
RETURNING id
""")
cursor.execute(insert_query, ('王芳', 'wang@company.com', '市场部', 13000))
new_id = cursor.fetchone()[0]
print(f"New employee ID: {new_id}")

# 提交事务
conn.commit()

except Exception as e:
print(f"Database error: {e}")
conn.rollback()

finally:
# 关闭连接
if conn:
conn.close()

十三、学习资源

  1. 官方文档 - 最权威的参考资料
  2. PGExercises - PostgreSQL交互式练习平台
  3. PostgreSQL Tutorial - 免费教程网站
  4. pgAdmin - 官方图形化管理工具
  5. PostgreSQL Weekly - 每周更新资讯
graph LR
A[学习基础SQL] --> B[掌握PostgreSQL特性]
B --> C[性能优化]
C --> D[高可用架构]
D --> E[扩展开发]
E --> F[成为PostgreSQL专家]

PostgreSQL作为功能最强大的开源数据库,适用于从嵌入式系统到企业级应用的各种场景。通过本教程,你已经掌握了其核心功能和高级技巧,建议结合实际项目深入实践。记住:正确的数据库设计比后期优化更重要

参考&致谢

🔲 ☆

PostgreSQL命令行使用教程:掌握 psql 工具

掌握PostgreSQL的命令行工具psql是高效管理数据库的关键。本文将带你全面了解这个强大的交互式终端工具的各种使用方法,包括各种常见问题和技巧总结。

🚀 启动psql

基本连接方式

# 连接到本地默认数据库
psql

# 指定用户名和数据库
psql -U username -d dbname

# 指定主机和端口
psql -h localhost -p 5432 -U postgres -d mydb

连接参数说明

参数 说明 示例
-U 用户名 -U admin
-d 数据库名 -d sales_db
-h 主机地址 -h db.example.com
-p 端口号 -p 6432
-W 强制密码提示
-f 执行SQL文件 -f setup.sql

🔍 常用元命令(以\开头)

数据库操作

-- 列出所有数据库
\l

-- 切换数据库
\c dbname

-- 创建新数据库
CREATE DATABASE newdb;

-- 删除数据库
DROP DATABASE olddb;

表操作

-- 列出当前数据库所有表
\dt

-- 查看表结构
\d users

-- 显示表详细信息
\d+ orders

-- 显示表、视图和序列
\dv

用户和权限管理

-- 列出所有用户
\du

-- 创建新用户
CREATE USER dev WITH PASSWORD 'secret123';

-- 修改密码
ALTER USER dev WITH PASSWORD 'newsecret456';

-- 授予权限
GRANT SELECT, INSERT ON customers TO dev;

信息查询

-- 显示当前连接信息
\conninfo

-- 显示SQL版本
SELECT version();

-- 显示当前时间
SELECT NOW();

-- 显示当前数据库
SELECT current_database();

文件操作

-- 执行SQL文件
\i path/to/script.sql

-- 将查询结果输出到文件
\o output.txt
SELECT * FROM products;
\o

帮助系统

-- 显示所有元命令帮助
\?

-- 显示SQL命令帮助
\h

-- 查看特定命令帮助
\h CREATE TABLE

📊 查询与编辑

基本查询

-- 简单查询
SELECT * FROM employees;

-- 条件查询
SELECT name, salary FROM employees WHERE salary > 50000;

-- 排序
SELECT * FROM orders ORDER BY order_date DESC;

-- 限制结果
SELECT * FROM products LIMIT 10;

多行编辑

-- 开启多行模式
\set PROMPT1 '%/%R%# '

-- 输入多行SQL语句
SELECT
first_name,
last_name,
department
FROM employees
WHERE hire_date > '2020-01-01';

-- 结束多行输入(分号后回车)
;

查询历史

-- 查看历史命令
\s

-- 保存历史到文件
\s history.sql

-- 执行历史命令(!后跟行号)
\! 15

🔄 导入导出数据

导出数据

# 导出整个数据库
pg_dump dbname > dbname.sql

# 导出特定表
pg_dump -t tablename dbname > table.sql

# 导出为CSV格式
\copy (SELECT * FROM users) TO '/path/to/users.csv' CSV HEADER

导入数据

# 导入SQL文件
psql -d dbname -f backup.sql

# 导入CSV文件
\copy users FROM '/path/to/users.csv' CSV HEADER

# 使用COPY命令(需要超级用户权限)
COPY employees FROM '/path/to/employees.csv' DELIMITER ',' CSV HEADER;

⚙️ 配置与定制

配置文件(.psqlrc)

在用户主目录创建.psqlrc文件:

-- 设置时间格式
\set HISTFILE ~/.psql_history- :DBNAME
\set HISTSIZE 1000

-- 自定义提示符
\set PROMPT1 '%[%033[1;33m%]%/%R%#%[%033[0m%] '

-- 自动提交
\set AUTOCOMMIT on

-- 常用别名
\set QUIET on
\echo '常用别名:'
\echo 'e: \\dt'
\echo 's: SELECT * FROM'
\set QUIET off

常用配置选项

-- 显示查询执行时间
\timing

-- 扩展显示模式
\x auto

-- 设置空值显示
\pset null '[NULL]'

-- 设置边框样式
\pset border 2

🛠️ 高级技巧

事务管理

-- 开始事务
BEGIN;

-- 执行多个操作
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- 提交或回滚
COMMIT;
-- ROLLBACK;

性能分析

-- 查看查询计划
EXPLAIN SELECT * FROM large_table WHERE condition = 'value';

-- 详细分析(实际执行)
EXPLAIN ANALYZE SELECT * FROM large_table;

-- 索引使用情况
SELECT * FROM pg_stat_user_indexes;

维护操作

-- 重建索引
REINDEX TABLE large_table;

-- 清理表空间
VACUUM FULL ANALYZE;

-- 收集统计信息
ANALYZE VERBOSE;

🚨 常见问题解决

连接问题

# 认证失败
psql: FATAL: password authentication failed for user "user"

# 解决方案:
# 1. 检查pg_hba.conf配置
# 2. 重置密码:ALTER USER user WITH PASSWORD 'newpassword';

权限问题

-- 权限拒绝
ERROR: permission denied for table tablename

# 解决方案:
GRANT SELECT, INSERT ON tablename TO username;

特殊字符处理

-- 包含引号的字符串
SELECT * FROM comments WHERE text E'contains \'quote\'';

-- 使用$tag$语法
DO $$
BEGIN
INSERT INTO logs (message) VALUES ('This contains ''quotes''');
END $$;

💡 实用技巧总结

  1. 历史命令:使用上下箭头键浏览历史命令
  2. 自动补全:Tab键补全对象名(表名、列名等)
  3. 变量设置:使用:variable存储和重用值
\set id 100
SELECT * FROM users WHERE id = :id;
  1. 快速编辑:使用\e打开编辑器编辑当前查询
  2. 执行系统命令\!后跟系统命令
\! ls -l /backups

📚 学习资源

  1. PostgreSQL官方文档
  2. psql命令行备忘单
  3. pgAdmin - PostgreSQL图形化管理工具

通过掌握这些psql命令和技巧,你将能够高效地管理和操作PostgreSQL数据库。不断练习和实践是成为数据库管理专家的关键!

参考&致谢

🔲 ☆

Postgres 17 与 18 版本性能对比

18版本新增两种替代方案:worker和io_uring。worker(新默认值)会让Postgres使用专用的后台工作进程处理所有I/O操作。io_uring因性能优势备受期待,它利用Linux的io_uring接口实现所有磁盘读取的异步处理,有望显著提升I/O性能。
元素周期表抱枕
🔲 ☆

探索 PostgreSQL 18 的全新 UUIDv7 支持

Postgres 18 中引入的 UUIDv7 解决了将完全随机的 UUIDv4 用作主键时存在的性能缺陷。通过加入时间戳,UUIDv7 确保新生成标识符具有天然排序性,从而实现高效的顺序插入、提升缓存利用率并减少索引碎片。
元素周期表抱枕
🔲 ⭐

再看看 SQL 中的 null

NULL 与任何值的运算结果都是 NULL

NULL 有一个很重要的特性:NULL 与任何值的运算结果都是 NULL

1
2
3
4
5
SELECT 1 = 1; -- true
SELECT 1 = NULL; -- null
SELECT NULL = NULL; -- null
SELECT 1 != NULL; -- null
SELECT NULL != NULL; -- null

这也就意味着,对于存在列 col BOOLEAN NULLABLE 的表,如果一行中 col 列的值为 NULL,则下面的四条查询都不会包含这行

1
2
3
4
5
6
7
-- 等于自不必说
SELECT * FROM "table" WHERE col = true;
SELECT * FROM "table" WHERE col = false;

-- 但不等于也不会包括值为 null 的行
SELECT * FROM "table" WHERE col != true;
SELECT * FROM "table" WHERE col != false;

IS NULL

我们其实基本都知道这点,所以我们在进行不等运算时通常会用 IS NULL / IS NOT NULL 特殊处理 NULL 列

1
2
SELECT * FROM "table" WHERE col is null OR col != true; -- 筛选 col = null 或 false
SELECT * FROM "table" WHERE col is null OR col != false; -- 筛选 col = null 或 true

IS TRUE / IS FALSE

但其实,除了 IS NULLIS 操作符后面还可以跟随 BOOL 值,那么,用 IS NOT 其实是一个更加精准的不等于操作

1
2
SELECT * FROM "table" WHERE col IS NOT true; -- 筛选 col = null 或 false
SELECT * FROM "table" WHERE col IS NOT false; -- 筛选 col = null 或 true

而对于不是 bool 类型的 nullable 列,我们则可以搭配使用 = !=IS

1
2
3
-- 筛选 col = null 或任何不为 1 的值
SELECT * FROM "table" WHERE col is null OR col != 1;
SELECT * FROM "table" WHERE col = 1 IS NOT TRUE;

concat

NULL 与任何值的运算结果都是 NULL,但在函数中则不一定(取决于具体实现)

以连接字符串为例,如果中间存在 NULL,用 || 连接属于运算符,中间任何一项为 NULL 则结果为 NULL,而用 concat 连接则是函数,中间出现的 NULL 会被忽略

1
2
SELECT 'hello-' || NULL || 'world'; -- null
SELECT concat('hello-', NULL, 'world'); -- hello-world

布尔逻辑

NULL 与任何值的运算结果都是 NULL,但在布尔逻辑中则不一样…… 试试看能不能说出下面的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
select not NULL;
select null or null;
select null and null;

select null OR true;
select true OR null;
select null OR false;
select false OR null;

select null AND true;
select true AND null;
select null AND false;
select false AND null;
答案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
select not NULL;          -- NULL
select null or null; -- NULL
select null and null; -- NULL

select null OR true; -- TRUE
select true OR null; -- TRUE
select null OR false; -- NULL
select false OR null; -- NULL

select null AND true; -- NULL
select true AND null; -- NULL
select null AND false; -- FALSE
select false AND null; -- FALSE

其实逻辑在于理解 NULL 代表着「未知」,与「真」「假」一起构成了一个三值集合

那么自运算,无论「未知的反面」还是「未知和未知」「未知或未知」都是未知,也因此都是 NULL

OR 的逻辑则是「有任何一个值为 TRUE 就是 TRUE」,因此,在 NULL 参与的运算中,存在 TRUE 则为 TRUE,不存在 TRUE 则为 NULL(继续未知)

AND 的逻辑则是「有任何一个值为 FALSE 就是 FALSE」,因此,在 NULL 参与的运算中,存在 FALSE 则为 FALSE,不存在 FALSE 则为 NULL(继续未知)

在聚合函数中

在聚合时,如果对 NULL 值进行聚合,它的数值是被完全忽略的 —— 一个例子是 avg,如果对 1, 2, 3, 4, NULL 做 avg,结果是 (1+2+3+4)/4

如果期望给 NULL 在聚合时一个默认值,可以用 coalesce 函数为它赋一个「默认值」

COALESCE

上面已经提过 coalesce 函数了,再说一句就是,coalesce 函数可以接受多个参数(而不只是两个),会返回第一个非 NULL 值

例如用 coalesce(first_name, nickname, email) 取用户「昵称」

NULLIF

pg 中还存在一个 nullif 函数,接收两个值,如果两个值相等则返回 NULL 否则返回第一个值,等价于 CASE WHEN a = b THEN NULL ELSE a END

这个函数主要用来「将零值转换为空值」;举个例子就是

1
2
3
4
SELECT 
NULLIF(TRIM(name), '') AS name,
NULLIF(status, 'N/A') AS status
FROM t;

还有就是搭配 NULL 的「可转换为其他类型」的特性

1
2
3
4
SELECT
-- 将 '' 直接转换成 date 是会报错的,但是先转换为 NULL 再转换为 date 就可以了
NULLIF(col_date, '')::date AS date
FROM t;

NULL 值在 PostgresQL 协议中的表示

虽然大概率不会引起混淆,但还是说一下,虽然我们用 psql 规则看到 NULL 值就像是文本一样,但它的底层传输是二进制,PG 规定用 len = -1 代表 NULL 值,所以不存在它与空字符串、null 字符串等混淆的情况

另外,特殊的,在 COPY 中,如果用的 text format(PG 的消息协议中,对于一个值存在 text 和 binary 两种 format),那么会用 \N 代表 NULL 值

参考:https://www.postgresql.org/docs/current/protocol-message-formats.html 中的 Query, Parse, Bind, RowDescription, DataRow

NULL 值在文件系统中的存储

当行中有任一列值为 NULL 时,「行头」HeapTupleHeaderData 中的 t_infomask 字段内的 HEAP_HASNULL flag 会被标记为 1,此时在行头后面、其余数据前面会增加一个 null bitmap,用位图的形式存储所有列的 NULL 情况,且如果某一列的值为 null,后面的 data 中将不会出现这一列的信息

另外,null bitmap 除了用来处理 NULL 值,还会用来处理 drop column —— 当一列被删除时其实际上依然存在着,只是后面所有的行都会带有 null bitmap 将这一列标记为 NULL(更事实上,删除列是懒删除,行内的数据都还在,只有下次更新行时才会清理这些数据 —— 当然,清理的方式也是将它标记为 NULL);

参考:https://www.postgresql.org/docs/current/storage-page-layout.html

🔲 ☆

俾Docker容器中的应用访问宿主机上的数据库服务

在Docker Compose中,默认情况下,服务之间会在一个自定义的网络中通信。因此,容器会通过这个网络进行互相通信,而无法直接访问宿主机的 IP 地址。

这便是为何当服务尝试连接宿主机上的数据库服务器地址(兹以PostgreSQL这一数据库服务以及192.168.1.1:5432这一服务器位址为例)时,会出现连接超时的问题。

为了解决这个问题,可以有几种方案来让Docker容器中的应用访问宿主机上的数据库,而无需使用Docker自己创建的网络。

方案 1: 使用 host.docker.internal

在Docker for Linux中,可以使用host.docker.internal来指向宿主机的IP地址。这是Docker提供的一个内置DNS名称,允许容器访问宿主机的网络资源。可以将数据库的HOST设置为host.docker.internal,这样容器内部会自动解析到宿主机的IP。

  1. 修改 settings.py.env 文件中的数据库配置,将 HOST 设置为 host.docker.internal

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': 'database',              # 改成自己的
            'USER': 'database',              # 改成自己的
            'PASSWORD': 'your_password',     # 改成自己的
            'HOST': 'host.docker.internal',  # 使用 host.docker.internal 而不是 192.168.1.1
            'PORT': '5432',
        }
    }
    
  2. 运行docker compose命令,尝试把容器架起来;容器会自动解析这个特殊的DNS名称,并连接到宿主机的PostgreSQL服务。

方案 2: 使用 network_mode: "host"

如果不想让Docker为容器创建单独的网络,可以使用network_mode: "host"配置项。这会让容器直接使用宿主机的网络堆栈,而不是通过Docker创建的网络。这意味着容器可以直接访问宿主机的网络接口。

  1. 修改 docker-compose.yml 文件,在 web 服务中添加 network_mode: "host"

    services:
      web:
        (从略)
        network_mode: "host"  # 添加这个选项
        (从略)
        ports:
          - "(所期望的容器外端口):8000"
    
  2. 重新运行docker compose up,此时Docker容器将直接使用宿主机的网络,因此它可以直接访问192.168.1.1:5432上的PostgreSQL。

方案 3: 自定义网络配置,桥接到宿主机网络

如果仍然想使用Docker自定义网络,但让容器能够访问宿主机的网络,可以使用extra_hosts来为容器提供宿主机 IP 的映射。

  1. docker-compose.yml中,使用extra_hosts指定宿主机的IP:

    services:
      web:
        (从略)
        ports:
          - "(所期望的容器外端口):8000"
        extra_hosts:
          - "host.docker.internal:192.168.1.1"  # 手动映射宿主机的 IP
    
  2. 运行docker-compose,这会将host.docker.internal映射到宿主机IP地址。

总结

  • 使用host.docker.internal是最简便的方法,这个DNS名会自动解析到宿主机的IP地址。
  • 如若希望容器直接使用宿主机网络,可以使用network_mode: "host",让容器与宿主机共享网络堆栈。
  • 如若欲继续使用Docker自定义的网络,但仍然访问宿主机服务,可以使用extra_hosts来手动指定宿主机 IP。

根据需求选择合适的方案,修改配置后应该可以解决Docker容器无法连接宿主机上数据库服务的问题。

🔲 ☆

afdian-linker 技术选型与 Vercel 部署指南 | 2025 年第 21 周草梅周报

本文在 草梅友仁的博客 发布和更新,并在多个平台同步发布。如有更新,以博客上的版本为准。您也可以通过文末的 原文链接 查看最新版本。

前言

欢迎来到草梅周报!这是一个由草梅友仁基于 AI 整理的周报,旨在为您提供最新的博客更新、GitHub 动态、个人动态和其他周刊文章推荐等内容。


技术分享

afdian-linker 的开发工作已经告一段落,之前也分享了一些开发心得(详见:afdian-linker 正式发布 | 2025 年第 18 周草梅周报),因此现在来简单的做一下技术选型上的分享。

框架选型

从立项开始,afdian-linker 就确定了要能够在 Vercel 等云服务平台上部署的要求,因此在框架选型上,优先考虑可以部署在 Vercel 上的框架。

Vercel 为例, Vercel 平台支持的框架包括 Next.js、SvelteKit、Nuxt、Astro、Remix、Vite 等,基本上主流的 CSR 和 SSR 框架都能够支持。

其中又以 Vercel 官方出品的Next.js支持性最佳,支持 Vercel 平台全部的特性和功能。

image-20250525172423998

这也是为什么目前主流的无服务器部署方案都推荐使用 Next.js 开发,因为通过 Vercel 部署实在太方便了。

不过 Next.js 是基于 React 开发的,对 React 生态更加友好。

出于技术选型的偏好,个人还是选择了 Vue 生态下的 Nuxt 框架,对标 Next.js,该有的功能也基本上都有。

无论是 Next.js、Nuxt,还是其他框架,在开发上都是大同小异的,没有本质区别,选择自己喜欢的框架开发即可。

Next.js 和 Nuxt 框架都是全栈框架,即在一个项目中同时编写前端和后端代码,集成了网页开发和接口开发,对于中小型项目,可以极大的省去前后端联调的时间,也可以增加代码的复用,节约开发和部署的时间。

数据库选型

在选择完开发框架后,就要选择数据库了。

在 afdian-linker 中,是要记录用户和订单等数据的,所以需要一个数据库来存储这些数据。

由于前面已经选择了在 Vercel 部署项目,因此这里也选择 Vercel 提供的 PostgreSQL 数据库。

image-20250525175409011

注意:Vercel 平台的 PostgreSQL 数据库是由合作的第三方提供的,例如 Neon 和 Supabase 都提供了 PostgreSQL 数据库,详见 Neon plansSupabase pricing,分别有 500MB 和 256MB 大小。

当然,这里也稍微提一下其他类型的数据库。

由于本项目是要部署到云服务上的,没有固定的服务器,因此像 SQLite 这样的本地数据库就不再适用。不过如果是单机部署的话,那么也可以考虑使用 SQLite ,以节约数据库的空间。

就个人经验而言,大多数情况下,SQLite 的性能已经足以支撑小型项目的业务了,毕竟很多时候都没那么多的用户。

此外,还可考虑使用 MySQL ,不过相较于 PostgreSQL ,提供免费试用的 MySQL 的云服务商比较少,个人推荐两个: TiDBAiven for MySQL

但这两个服务商还各有各的问题,TiDB 虽然提供 5 个 5 GB 的兼容 MySQL 的分布式数据库集群(参考:Pricing Details),但正如官方所说,TiDB 并不是 MySQL ,也就是身说,不是完全兼容 MySQL 的,可能存在一些细节上的差异。由此带来的问题,需要小心调试。不过优点就是,TiDB 在国内可以直连,使用上还是比较方便的。

而 Aiven 就略显尴尬,Free plans 虽然提供免费的 1GB 的 PostgreSQL 和 MySQL 数据库(近期从 5GB 下调为 1GB 了),不过 Aiven 本身在国内无法直连,仅适合项目部署在境外服务器或云服务商时使用。

在本项目中,由于 Vercel 本身也是在境外的,因此可以使用 Aiven 的数据库

当然了,如果更喜欢 NoSQL 的话,也可以用MongoDB,官方也提供了 512 MB 的试用。

缓存数据库的选型上,毫无疑问的选择 Redis(Vercel 也提供了)。

项目开发

项目开发中的心得已在《afdian-linker 正式发布 | 2025 年第 18 周草梅周报》一文中进行了详细说明,此处不再赘述。

程序员使用 AI 工具写的项目水平,不会超过他自己水平的上限;反之,也不会低于自己水平的下限。

代码库中的代码质量,依旧是由程序员自己的水平决定的。

AI 工具的使用不会超越程序员自身的水平,但能显著提高效率。

开发总结

这次额外提一点,很多人以为在 AI 大模型出来后,就可以实现人人都能开发自己的软件,写自己的项目了。

这句话错也没错。

没错是因为,AI 大模型在客观上讲,将软件开发中存在技术难度的部分——代码编写——的开发难度大大降低了,可以通过自然语言去描述需求和写代码,这确实加快了很多写代码的速度。

不过,说它错,也是因为,一个完整的项目开发流程中,编码只是其中的一小部分,一个环节而已,并不代表全部。

仅以本文在之前描述的两个环节,框架选型和技术选型上,一个从未有过编程和项目部署经验的人,最大可能性是卡在哪一步呢?

答案是:在进入框架选型和技术选型前,就已经找不着方向了,因为真正的新人甚至不知道该从哪里开始。(这也是为什么出现了一些一站式集成开发的 AI 网站,提供从开发到部署的全流程服务)。

可以说,AI 大模型可以加速编程,其实是已经掌握了编程技能的程序员的特权。

此外,想必各位程序员也听说过这样一句话:接手一个老项目,往往重新开发会比接着写更快。

这是为什么呢?因为在项目开发的时候,不同的人往往有不同的思路,而接手别人的代码,就意味着要去理解当初写这段代码的思路,这实际上并不是一件容易的事情。除此之外,还有代码风格、编码习惯等小问题。

在我看来,AI 编程实际上相当于人类去接手 AI 编写的代码。虽然 AI 编写的代码质量不一定低,甚至还比人类高,但,能否让接手的人类可以理解,恐怕还是个问题。

从这个角度看,就可以理解为什么人类总是看不懂 AI 编写的代码了,因为那其实也相当于接手了 AI 开发的“屎山”。

为了避免或减少此类问题,还是需要人工手动审查 AI 编写的代码,及时纠正错误写法,或者要求 AI 重新编写。

项目部署

image-20250525183935662

在 Vercel 上部署项目是非常简单的,如果是自己的仓库的项目,只要直接import即可。

image-20250525184253679

如果是第三方项目,也只要导入对应的仓库地址即可。

此外,afdian-linker 还支持一键部署。

点击下方按钮一键部署到 Vercel。

Deploy with Vercel

image-20250525184215729

创建完项目后,就是修改构建命令和填写环境变量。

image-20250525184519065

一般来说,Vercel 默认的构建命令已经是可以用的了,无需特别修改即可正常运行。

如需修改,可以按实际情况改动。

image-20250525184625876

而环境变量,则按照文档说明填写即可。

修改环境变量之后记得重新部署

到这一步,一切顺利的话,项目已经可以正常运行了,可以尝试通过 Vercel 提供的默认域名进行访问。

以 afdian-linker 为例,可以通过 https://afdian-linker.vercel.app/ 访问(需要科学上网)

绑定域名

你可能会注意到,Vercel 提供的默认域名是无法直接访问的,vercel.app在国内无法直接连接,因此需要一个自己的域名用于直接访问。

此处不会赘述如何购买域名,可以自行在国内国外域名网站中购买(提供一个域名比价网:https://tld-list.com/)。

image-20250525185133924

在 Vercel 的 Domains 中进行配置即可。

修改函数区域

在 Vercel 部署的 Next.js、Nuxt 等全栈项目中,后端接口能力都是由 Vercel 的云函数(Vercel Functions)提供的,因此 Vercel Functions 的访问速度会直接影响用户体验。

image-20250525185600969

在 Vercel 的 Function Region 页面中,修改云函数的部署区域即可。

如果是面向国内用户,则建议部署在距离更近的香港地区。

面向哪个国家和地区的用户就把云函数部署在哪个国家和地区

修改部署区域之后记得重新部署

部署总结

虽然通过 Vercel 部署项目确实挺简单的,不过因为一些客观原因,想要访问 Vercel 却并不容易,这也是 AI 无法解决的问题。

可以说,在一个项目的完整流程中,只有从开发完毕到成功部署,才算真正完成了项目开发。

为什么只说是项目开发呢?因为一个真正的软件项目,只有真的投入使用后,才是一个切实可用的真实项目。

任何未经用户实际检验的项目,都只是开发者的练手项目而已。

如果算上这一步,可见,AI 大模型无法解决的问题会越来越多,这也就是为什么我说“有了 AI 大模型,也不等于人人都能开发自己的软件”,对软件工程还是要有一定的敬畏之心,对项目运营更要有敬畏之心。

以上就是本人对这次 AI 开发开源项目的一次简单的开发心得、技术选型和部署指南分享,如有错漏,欢迎指正。

最新 GitHub 加星仓库

  • CaoMeiYouRen starred cmd-generator - 2025-05-24 01:44:44
    该内容描述了一个通过点击按钮生成 CMD 命令的项目。主要编程语言为 TypeScript,项目在 GitHub 上获得了 27 个星标。
  • CaoMeiYouRen starred FFmpegFreeUI - 2025-05-24 01:44:11
    3FUI 是一款基于 ffmpeg 的 Windows 平台专业交互外壳,主要用于视频转码。该软件的开发动机源于对现有转码工具的不满,开发者希望通过自己的努力提供更好的解决方案。3FUI 使用 Visual Basic .NET 作为主要编程语言,并在 GitHub 上获得了 615 个星标。

其他博客或周刊推荐

阮一峰的网络日志

阿猫的博客

潮流周刊

二丫讲梵的学习周刊

总结

本周的更新和动态如上所示。感谢您的阅读!
您可以通过以下方式订阅草梅周报的更新:

往期回顾

本文作者:草梅友仁
本文地址: https://blog.cmyr.ltd/archives/2025-21-caomei-weekly-afdian-linker-tech-selection-deployment-guide.html
版权声明:本文采用 CC BY-NC-SA 4.0 协议 进行分发,转载请注明出处!

🔲 ⭐

检查PostgreSQL数据库服务器是否真的已经启动

导入

执行启动命令后,可以通过几种方式来检查 PostgreSQL 数据库服务器是否真的已经启动。

使用命令行工具检查

可以使用 pg_isready 命令来检查数据库服务器的运行状态。在终端中执行以下命令:

pg_isready -p 5432

如果数据库服务器正在运行并监听指定的端口(在这里是5432),命令会返回 “accepting connections”,表示服务器已经启动并可以接受连接。

查看日志文件

启动数据库服务器后,可以查看日志文件以获取更多详细信息。例如,假设日志文件的位置是 /var/log/postgresql/postgresql-12-main.log。则可以使用 tail 命令查看最后几行日志:

tail /var/log/postgresql/postgresql-12-main.log

如果服务器成功启动,日志文件中应该会显示相应的信息。

尝试连接到数据库

最直接的方式是尝试连接到数据库并执行一些查询。可以使用 PostgreSQL 的客户端工具(如 psql)连接到数据库并执行一些简单的查询语句。在终端中执行以下命令:

psql -h localhost -p 5432 -U postgres

这将连接到本地主机上的 PostgreSQL 数据库(假设数据库服务器在本地主机上),端口为 5432,并使用 “postgres” 用户身份登录。如果成功连接并登录到数据库,表示数据库服务器已经启动。

总结

通过以上方法之一,可以验证 PostgreSQL 数据库服务器是否已经成功启动。

❌