Axum中通过共享状态注入PgConnection的并发锁问题
解决Axum中PgConnection共享导致的锁竞争问题
你当前的核心问题在于用Arc<Mutex<PgConnection>>共享单个数据库连接——同一时间只能有一个请求持有锁并使用连接,直接让Axum多Worker的并行能力完全失效,所有请求都会串行执行。
正确的做法是使用sqlx内置的数据库连接池(PgPool),连接池本身就是线程安全的,不需要额外加锁,还能自动管理连接的创建、复用与回收,完美适配Axum的并发模型。
步骤1:修改AppState结构
把单个连接替换成连接池:
use sqlx::postgres::PgPool; pub struct AppState { pub db_pool: PgPool, pub jwt: JWTSettings, }
步骤2:初始化连接池
在启动Axum服务时创建并初始化连接池:
async fn init_db_pool() -> PgPool { // 替换成你的数据库连接字符串 PgPool::connect("postgres://user:password@localhost/your_db") .await .expect("Failed to initialize database pool") } #[tokio::main] async fn main() { let db_pool = init_db_pool().await; let jwt_settings = JWTSettings::load().unwrap(); let app_state = Arc::new(AppState { db_pool, jwt: jwt_settings }); let app = Router::new() .route("/signup", post(sign_up)) .with_state(app_state); axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()) .serve(app.into_make_service()) .await .unwrap(); }
步骤3:路由中使用连接池
不需要锁,直接从池里异步获取连接,用完自动归还:
pub async fn sign_up( State(state): State<Arc<AppState>>, Json(signup_payload): Json<SignupPayload>, ) -> Result<Json<LoginResponse>, StatusCode> { // 异步获取连接,无可用连接时会挂起当前任务,不阻塞线程 let connection = state.db_pool.acquire().await .map_err(|err| { eprintln!("Failed to get db connection: {:?}", err); StatusCode::INTERNAL_SERVER_ERROR })?; // 直接用连接执行查询,无需可变引用 let existing_user = sqlx::query!("select * from users where username=$1", signup_payload.username) .fetch_one(&connection) .await .map_err(|err| { eprintln!("Query failed: {:?}", err); StatusCode::INTERNAL_SERVER_ERROR })?; // 后续业务逻辑... Ok(Json(LoginResponse { /* 填充响应字段 */ })) }
为什么这能解决问题?
- PgPool内部已经实现了线程安全的连接管理,无需额外的
Mutex或Arc包装 acquire()是异步操作,不会阻塞线程,当连接池满时,请求会排队等待可用连接,其他请求仍能正常处理- 每个请求独立获取连接,多Worker线程可以并行处理不同请求,完全发挥Axum的并发优势
你还可以通过PgPoolOptions调整连接池的最大连接数、超时时间等参数,适配你的业务负载:
use sqlx::postgres::PgPoolOptions; async fn init_db_pool() -> PgPool { PgPoolOptions::new() .max_connections(20) // 设置最大连接数 .connect("postgres://user:password@localhost/your_db") .await .expect("Failed to initialize database pool") }
内容的提问来源于stack exchange,提问作者Karan Kumar
相关产品推荐
相关产品推荐

