Go 语言并发数据库操作需合理配置连接池、明确事务边界、避免长事务和连接泄漏;必须显式设置 SetMaxOpenConns、SetMaxIdleConns 等参数,事务须单 goroutine 执行并显式提交或回滚,只读用连接池、强一致写用事务、跨服务用最终一致性。
Go 语言通过 database/sql 包原生支持并发数据库操作,但默认连接池和事务行为若不加控制,容易引发连接耗尽、死锁或数据不一致。关键不在“开多个 goroutine”,而在合理配置连接池、明确事务边界、避免长事务和连接泄漏。
默认连接池(最大连接数 0,即无限制;空闲连接数 2)在
高并发下极易打垮数据库。必须显式调优:
MaxOpenConns 相同或略低(如 50),减少连接反复建立/销毁开销3 * time.Minute),强制复用老连接前重连,规避网络中断或数据库连接超时问题1 * time.Minute),及时清理长期空闲连接,释放数据库资源事务不是并发安全的,*sql.Tx 对象不能被多个 goroutine 同时使用。常见错误是把 tx 传入多个协程执行不同语句——这会 panic 或行为未定义。
tx.Query/Exec 操作tx.Commit() 或 tx.Rollback(),建议用 defer tx.Rollback() 开头,再在成功时显式 tx.Commit() 覆盖不是所有操作都需要事务,也不是所有并发都该共用一个连接池:
db.Query/QueryRow,走连接池,无需事务db.BeginTx 创建事务,全程用该 tx 对象操作,结束后立即提交或回滚连接异常往往表现为超时、"too many connections" 或 goroutine 堆积。可通过以下方式定位:
db.Stats() 获取 OpenConnections、InUse、Idle 等指标,暴露到 Prometheussql.Open 后的 db.SetConnMaxLifetime 和 SetConnMaxIdleTime 并配合理日志,确认连接是否及时回收pprof 查看 goroutine 堆栈,若大量卡在 db.Query 或 tx.Commit,说明连接池瓶颈或事务未关闭不复杂但容易忽略:事务对象不可复用、连接池参数不设等于裸奔、长时间运行的事务是并发杀手。