跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何在Golang中操作PostgreSQL数据库 Go语言pgx库高性能实践

用 pgxpool.Connect 配连接池,设 MaxConns 控制大小,程序退出前调 Close();查单行用 QueryRow 并 Scan,多行用 Query 并 Close;批量用 pgx.Batch,建表优先 timestamptz。 pgx 连接池怎么配才不泄漏内存 用
pgxpool.Connect
而不是
pgx.Connect
,后者只建单连接,没池、不复用、一请求一连就崩。连接池必须显式关闭,否则 goroutine 和 socket 会一直挂着。
pgxpool.Connect
返回的
*pgxpool.Pool
需在程序退出前调用
Close()
,比如 defer pool.Close() 或在 main 结束时关 连接池大小别硬写死,用
pgxpool.Config.MaxConns
控制上限,小服务设 10~20 足够,大并发看
pg_stat_activity
实时观察 环境变量里传 DSN 时,记得加
sslmode=disable
(本地开发)或
sslmode=require
(生产),漏了会卡住连接、超时后报
dial tcp: i/o timeout
Query 和 QueryRow 该选哪个 查单行且确定有结果,用
QueryRow
;查多行、不确定条数、要遍历,用
Query
。错用会导致 panic 或漏数据——
QueryRow
遇到零行直接返回
sql.ErrNoRows
,而
Query
遇到零行只是返回空结果集,不会报错。
QueryRow
后必须调
Scan()
,否则连接不会归还池里,积压后触发
context deadline exceeded
Query
返回
*pgx.Rows
,用完必须
rows.Close()
,不然连接一直被占着,哪怕用
for rows.Next()
遍历完了也不自动关 想查一行但字段可能为空?别用
QueryRow.Scan(&v)
直接扫,改用
Scan(&sql.NullString{})
或 struct tag 加
pgtype:"text"
配合自定义类型 批量插入为什么比 for 循环快十倍 因为
pgx.Batch
把多条语句打包成一个网络往返,避免 TCP 握手和 PostgreSQL 解析开销。普通 for 循环每 insert 一次都走完整 round-trip,QPS 直接掉到 1/10。 用
pool.Begin()
开事务 +
batch := &pgx.Batch{}
累积语句 +
br := pool.SendBatch(ctx, batch)
提交,比
pool.Exec
单条快得多 batch 大小建议控制在 100~1000 条之间,太大容易 OOM 或触发 PostgreSQL 的
max_stack_depth
限制 注意 batch 不支持 RETURNING,要拿插入后的 ID?得切回单条
QueryRow
或改用
INSERT ... SELECT UNNEST(...)
方式 time.Time 存进 PostgreSQL 总是差 8 小时 根本原因是 Go 默认用本地时区解析 time.Time,而 PostgreSQL 的
timestamp without time zone
按 UTC 存,
timestamp with time zone
才存时区信息。两边时区没对齐,就偏移。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 立即学习 “ go语言免费学习笔记(深入) ”; 建表时优先用
timestamptz
(即
timestamp with time zone
),Go 侧
time.Time
值自带时区信息,pgx 能自动转换 如果必须用
timestamp
(无时区),写入前统一转成 UTC:
t.UTC()
,读出来再按需转本地时区 别依赖
time.Local
,Docker 容器或 Linux 服务器上它可能是 UTC,本地 macOS 可能是 CST,行为不一致 最麻烦的其实是 NULL 时间字段和零值时间混在一起——Go 的
time.Time{}
是 0001-01-01,PostgreSQL 当成非法时间报
invalid input syntax for type timestamp
。得用
*time.Time
或
pgtype.Timestamptz
显式处理空值。

相关文章