连接池
Pool<DB> 和 Postgres 无关,代码都在 sqlx-core/src/pool/ 里:inner.rs 623 行(PoolInner:借、还、建连接、后台任务)、connection.rs 421 行(PoolConnection 和它的 Drop)、options.rs 596 行(PoolOptions,一半是文档)、mod.rs 668 行(Pool 的公开方法,大半是文档)。许可的计数交给 sqlx-core/src/sync.rs 的 AsyncSemaphore,在 tokio 下它就是 tokio::sync::Semaphore。驱动只提供三样东西:connect、ping、close,Postgres 的 ping 是一个 Sync 来回。
三页按一条连接的一生排:先看池的配置,再看借出,最后看归还和后台回收。实验都在 M2 Max、macOS、rustc 1.99.0、Postgres 16.14 上跑,池里有几条连接用 pool.size()、pool.num_idle() 和服务端的 pg_stat_activity 一起看,线上发了什么用一次查询的全过程里那个打印协议消息的代理看。
- PoolOptions 与默认值:默认值都写在
PoolOptions::new里(10 条、30 秒、10 分钟、30 分钟、借出时 ping);三个回调after_connect/before_acquire/after_release各在什么时候跑、拿到什么元数据;connect建池时至少连一条,connect_lazy一条都不连;fair在 tokio 下不能关。 - 获取连接:
acquire的循环:拿许可(先到先得),弹空闲连接并 ping,没有就加计数、新建;连接被拒或服务端还在启动时从 10 毫秒开始指数退避重试;一切都在acquire_timeout之内,超时一律报PoolTimedOut;超过 2 秒打一条WARN。 - 归还、Drop 与维护任务:
Drop只 spawn 一个任务,归还时再 ping 一次,先推回空闲队列再放许可;close_on_drop、detach、leak对计数和许可的影响;后台任务按两个超时中较小的那个周期回收连接,只在关掉连接之后补min_connections;Pool::close要等所有借出的连接回来。
flowchart TB opts["PoolOptions 配置"] --> acq["acquire 借出"] acq --> use["用户使用连接"] use --> drp["Drop 后 spawn 归还"] drp --> idle["空闲队列"] idle --> acq idle --> reap["维护任务回收"] reap --> fill["补足最小连接数"]
事务怎么借用池里的连接、Transaction 被 drop 时排队的 ROLLBACK 什么时候发出去,见事务;信号量本身怎么做到先到先得,见 tokio 卷的 batch_semaphore。
💬 关联讨论
发起讨论加载中...