连接池默认是多大?耗尽时会怎样?连接被服务端断掉之后会不会出错?多个 gunicorn worker 会把数据库连接数撑到多少?这篇用真实的 PostgreSQL 逐项验证。
类型: QueuePool | pool_size = 5 | max_overflow = 10 | timeout = 30.0 | recycle = -1 | pre_ping = False 刚创建: Pool size: 5 Connections in pool: 0 Current Overflow: -5 Current Checked out connections: 0 | PG 连接数 0 借出 2 个连接: Pool size: 5 Connections in pool: 0 Current Overflow: -3 Current Checked out connections: 2 | PG 连接数 2 归还 1 个: Pool size: 5 Connections in pool: 1 Current Overflow: -3 Current Checked out connections: 1 | PG 连接数 2 engine.dispose() 之后 PG 连接数 0
上一篇:Rollback 的实际行为;下一篇:Pool Checkout 与连接释放。
借 3 个(2 + 1 溢出): Pool size: 2 Connections in pool: 0 Current Overflow: 1 Current Checked out connections: 3 | PG 连接数 3 借第 4 个 → 等了 1010 ms 后 TimeoutError: QueuePool limit of size 2 overflow 1 reached, connection timed out, timeout 1.00 (Background on 归还 1 个连接后 PG 连接数: 3 (池里还有空位,这个连接被留在池里,没有关闭) 再归还 1 个后: 3 | 池状态: Pool size: 2 Connections in pool: 2 Current Overflow: 1 Current Checked out connections: 1 三个都归还后:2(池只保留 pool_size=2 个,多出的那个溢出连接被真正关闭) | 池状态: Pool size: 2 Connections in pool: 2 Current Overflow: 0 Current Checked out connections: 0
默认(无 pre_ping) 服务端杀掉空闲连接后下一次查询 → OperationalError: terminating connection due to administrator command
(没有 pre_ping 时,失败那次之后坏连接被丢弃,再查一次 → 成功)
pool_pre_ping=True 服务端杀掉空闲连接后下一次查询 → 成功(池发现连接坏了,换了一个新的)第 100 篇会专门讲断线后的恢复。
QueuePool 中位数 0.17 ms NullPool 中位数 1.82 ms
1 个 worker × 16 线程,40 个并发请求(每个查询 0.5 秒):PG 上最多同时有 5 个连接(每个池上限 3 + 2 = 5,1 个池最多 5),总耗时 4.1 秒,状态码 [200] 3 个 worker × 16 线程,40 个并发请求(每个查询 0.5 秒):PG 上最多同时有 15 个连接(每个池上限 3 + 2 = 5,3 个池最多 15),总耗时 1.5 秒,状态码 [200]
这一节用 gunicorn 的 gthread worker,每个 worker 进程里一个独立的 Engine。