Golang
【GORM】连接池完整工作流程
02-03 15:49连接池完整工作流程(对应你的描述)
用「分步场景」拆解,更直观:
GORM 启动阶段:进程启动,配置MaxOpenConns=100,但无任何 MySQL 连接,连接池是空的;
第 1 个请求到来:
连接池无可用连接,创建「连接 1」;
执行 SQL 后,「连接 1」放回连接池(成为空闲连接);
第 2 个请求到来:
直接复用池中的「连接 1」,无需新建;
执行完放回池,继续空闲;
第 3 个请求单独到来:
还是复用「连接 1」,连接池仍只有 1 个连接;
同时来 3 个请求:
第 1 个请求用「连接 1」;
第 2、3 个请求无可用连接,创建「连接 2」「连接 3」;
3 个请求执行完,「连接 1/2/3」都放回连接池(此时池中有 3 个空闲连接);
下一波来 2 个请求:
直接复用「连接 1/2」,无需新建;
下一波来 5 个请求:
先复用池中的 3 个连接(1/2/3);
剩余 2 个请求创建「连接 4/5」;
执行完后,5 个连接都放回池;
直到请求数触发上限:
当并发请求数导致连接数达到MaxOpenConns=100,新请求会排队等待(而非报错),直到池中有空闲连接释放。
补充 2 个关键细节(避免踩坑)
1. 空闲连接的「回收规则」
不是所有放回池的连接都会一直留着:
若配置了SetConnMaxIdleTime=30分钟,「连接 1」如果 30 分钟没被复用,会被连接池主动关闭,池内连接数减少;
若池内空闲连接数超过MaxIdleConns(比如设为 50),多余的空闲连接也会被回收(比如池里有 60 个空闲连接,会关掉 10 个)。
2. 「排队」vs「报错」的边界
当请求数超过MaxOpenConns,连接池不会立刻报错,而是让新请求等待空闲连接(等待时长由数据库驱动 / 超时配置决定);
若等待超时(比如配置了SetConnMaxLifetime或驱动超时),才会抛出「获取连接超时」的错误。
总结
GORM 连接池是「按需创建连接」,而非启动时一次性创建,上限由MaxOpenConns控制;
连接用完后会放回池复用,直到被回收(空闲超时 / 存活超时)或进程关闭;
并发请求≤池内空闲连接数:直接复用;并发请求>空闲连接数:新建连接(不超上限);超上限:排队等待。
这个逻辑是 Go 数据库连接池的核心,理解后你就能精准配置参数,既保证并发能力,又不会占满 MySQL 连接导致其他程序无法使用。