🔥 博主简介:专注后端开发、数据库实战、Python高性能编程,持续分享零基础入门干货,手把手教大家落地技术项目。
📌 本文核心亮点
-
保姆级 PostgreSQL Windows下载+安装+环境配置,零基础零踩坑
-
基于 psycopg_pool 异步 连接池 实现高性能数据库操作
-
完整实战:建表、单条新增、批量新增、查询、更新、删除(CRUD全覆盖)
-
代码可直接复制运行,附带详细注释、问题排查、核心原理讲解
✅ 适用人群:PG新手、Python后端开发者、需要学习数据库基础CRUD的同学
✅ 运行环境:Windows10/11、Python3.8+、PostgreSQL15+/16+/18+
一、PostgreSQL 简介
PostgreSQL(简称PG)是一款开源、免费、高性能、支持事务、支持复杂查询的关系型数据库,相比MySQL,其在大数据量、复杂业务、事务一致性、自定义数据类型上优势显著,是企业级后端开发的主流数据库之一。
核心特性:
-
完全开源免费,商用无版权风险
-
完美支持ACID事务、主从复制、索引优化
-
支持JSON、数组、地理信息等特殊数据类型
-
稳定性极强,适合长期线上项目使用
二、PostgreSQL Windows 保姆级安装教程
2.1 官方下载安装包
官方下载地址:PostgreSQL: Windows installers
1、打开官网,点击 Download the installer(EDB官方图形化安装包,新手首选)
2、选择最新稳定版(推荐16/18版本),架构选择 Windows x86-64
3、下载完成后得到 exe 安装包(约300M),右键以 管理员 身份运行,避免权限报错
2.2 详细安装步骤
1、欢迎界面直接点击 Next
2、选择安装路径(建议默认,不要中文路径),Next
3、组件选择:默认全选(PG服务、pgAdmin4图形工具、命令行工具),Next
4、设置超级用户 postgres 密码(重点!务必记住),后续连接数据库必须使用
5、端口默认 5432(PG默认端口,无需修改),Next
6、地区Locale选择 Default,适配系统编码,Next
7、确认配置,点击 Install 等待安装完成
8、取消启动StackBuilder勾选,直接Finish,安装完成
2.3 环境变量配置(必做)
为了让系统全局识别psql命令,需要配置环境变量:
1、找到PG安装目录下的bin目录,示例:
C:\Program Files\PostgreSQL\18\bin
2、此电脑-属性-高级系统设置-环境变量-系统变量-Path
3、新建,粘贴上述bin路径,一路确定保存
2.4 验证安装成功
打开cmd,输入以下命令,无报错即为成功:
bash
psql --version
同时可打开桌面pgAdmin4图形工具,输入刚才设置的密码,可可视化管理数据库。
三、Python环境准备(异步连接PG)
本文采用 psycopg_pool 实现异步数据库连接池,相比单连接,连接池可以复用数据库连接、提升并发性能,是生产级项目首选方案。
3.1 安装依赖库
bash
pip install psycopg-pool asyncio
核心依赖说明:
-
psycopg-pool:PostgreSQL官方异步连接池工具
-
asyncio:Python原生异步协程库,实现异步数据库操作
3.2 核心配置说明
项目中通过 DSN 字符串连接PG数据库,标准格式:
bash
postgresql://用户名:密码@localhost:5432/数据库名
默认本地配置:
-
用户名:postgres
-
端口:5432
-
地址:localhost
四、完整实战代码(建表+CRUD)
以下代码为可直接运行的生产级异步 PG 操作代码,包含:连接池初始化、建表、单增、批量增、查询、更新、删除全功能,附带超详细注释。
python
import asyncio
import selectors
from psycopg_pool import AsyncConnectionPool
from app.core.config import settings
from app.core.database import get_meta_pool
# 初始化PostgreSQL异步连接池
pool = AsyncConnectionPool(
settings.POSTGRES_DSN, # 读写账号数据库DSN
min_size=1, # 连接池最小常驻连接数
max_size=10, # 连接池最大连接数(控制并发上限)
open=False, # 不自动开启连接,代码手动开启(生产规范)
)
# ====================== 1. 创建数据表 ======================
async def create_table():
"""创建文章数据表"""
async with pool.connection() as conn, conn.cursor() as cur:
await cur.execute("""
CREATE TABLE IF NOT EXISTS articles2 (
id SERIAL PRIMARY KEY,
title VARCHAR(200) NOT NULL,
content TEXT,
create_at TIMESTAMP DEFAULT NOW()
)
""")
await conn.commit()
print("✅ 数据表创建成功")
# ====================== 2. 单条新增数据 ======================
async def insert_data(title, content):
"""新增单条文章数据,返回新增数据ID"""
async with pool.connection() as conn, conn.cursor() as cur:
# RETURNING id 新增后直接返回主键ID
await cur.execute(
"INSERT INTO articles(title, content) VALUES(%s, %s) RETURNING id;",
(title, content)
)
row = await cur.fetchone()
print(f"新增数据主键:{row}")
return row[0]
# ====================== 3. 批量新增数据 ======================
async def batch_insert(items: list[tuple]):
"""批量插入多条数据,提升写入效率"""
async with pool.connection() as conn:
async with conn.cursor() as cur:
await cur.executemany(
"INSERT INTO articles(title, content) VALUES(%s, %s)",
items
)
await conn.commit()
print(f"✅ 批量插入{len(items)}条数据成功")
# ====================== 4. 查询全部数据 ======================
async def query_all():
"""查询所有文章数据,格式化输出字段+值"""
async with pool.connection() as conn, conn.cursor() as cur:
await cur.execute("SELECT id, title, content FROM articles ORDER BY id DESC;")
# 获取所有数据
rows = await cur.fetchall()
# 获取数据表字段名
cols = [desc.name for desc in cur.description]
print("📌 字段列表:", cols)
print("📌 所有数据:")
# 遍历格式化输出
for row in rows:
print(dict(zip(cols, row)))
# ====================== 5. 更新数据 ======================
async def update_article(art_id: int, new_title: str):
"""根据文章ID更新标题,返回受影响行数"""
async with pool.connection() as conn, conn.cursor() as cur:
await cur.execute(
"UPDATE articles SET title=%s WHERE id=%s",
(new_title, art_id)
)
await conn.commit()
print(f"✅ 更新成功,影响行数:{cur.rowcount}")
return cur.rowcount
# ====================== 6. 删除数据 ======================
async def delete_article(art_id: int):
"""根据ID删除文章,返回受影响行数"""
async with pool.connection() as conn, conn.cursor() as cur:
await cur.execute("DELETE FROM articles WHERE id=%s", (art_id,))
await conn.commit()
print(f"✅ 删除成功,影响行数:{cur.rowcount}")
return cur.rowcount
# 主函数:测试所有功能
async def main():
# 手动开启连接池,阻塞等待资源,避免并发报错
await pool.open(wait=True)
# 取消注释即可测试对应功能
# await create_table()
# print("新增ID:", await insert_data("俄乌战争","即将结束....."))
# await batch_insert([("标题A", "内容A"), ("标题B", "内容B")])
# await query_all()
# await update_article(2, "新三国演义")
await delete_article(2)
# 程序入口
if __name__ == '__main__':
# 适配Windows异步事件循环,解决win32兼容问题
asyncio.run(
main(),
loop_factory=lambda: asyncio.SelectorEventLoop(selectors.Selector())
)
五、核心功能逐行解析
5.1 异步连接池核心参数
-
min_size=1:连接池最少保留1个连接,避免频繁创建销毁连接
-
max_size=10:最大10个连接,限制数据库并发压力,防止拖垮数据库
-
open=False:关闭自动连接,手动open更安全,符合生产最佳实践
-
wait=True:连接池满时阻塞等待,不直接抛出异常,提升程序稳定性
5.2 数据表字段解析
-
SERIAL PRIMARY KEY:自增主键,等同于MySQL的auto_increment
-
VARCHAR(200) NOT NULL:非空字符串,限制最大长度200
-
TEXT:长文本类型,无长度限制,适合文章内容
-
DEFAULT NOW():默认当前时间,自动填充创建时间
5.3 CRUD核心亮点
-
单条新增RETURNING:新增数据后直接返回主键ID,无需二次查询
-
批量插入executemany:循环插入效率极低,批量API大幅提升写入性能
-
字段动态匹配:通过cur.description自动获取字段名,适配任意数据表
-
rowcount返回行数:精准判断更新/删除是否生效
六、常见报错与解决方案
6.1 端口5432被占用
解决方案:重启PostgreSQL服务,或修改配置文件端口,重启服务
6.2 密码连接失败
解决方案:确认postgres用户密码正确,修改DSN中的账号密码
6.3 Windows异步循环报错
解决方案:代码中指定 SelectorEventLoop,适配Windows系统异步机制(本文代码已适配)
6.4 连接池耗尽报错
解决方案:合理调整max_size,业务结束自动释放连接,避免连接泄露
七、总结
本文完成了 PostgreSQL 从零安装配置 + Python异步 连接池 + 全套 CRUD 实战,所有代码均为可直接落地的生产级代码,区别于传统同步操作,异步连接池更适合高并发后端项目。
后续可以基于本文代码拓展:数据库事务、索引优化、分页查询、条件删除、多表关联查询等进阶操作。
💡 码字不易,点赞收藏关注!后续持续更新PG进阶、数据库优化、Python后端实战干货~