Rust sqlx执行INSERT无数据变更 重复插入报已存在错误
问题原因
核心问题是Postgres连接配置漏传了目标数据库名称。
构建PgConnectOptions时你只配置了主机、端口、用户名、密码、SSL模式,没有调用.database()方法指定要连接的业务库,此时sqlx会默认连接与用户名同名的数据库(多数场景下是默认的postgres系统库,或是和数据库账号同名的空库):
- 执行INSERT时实际写入的是这个默认库,不是预期的业务库,所以查询业务库看不到任何数据变更
- 反复往这个默认库的同一张表插入带相同唯一键的数据,自然会触发唯一约束冲突,返回记录已存在的错误
修复步骤
- 补全连接配置的数据库名参数,修改连接初始化代码如下:
let from_ssl = |ssl: bool| -> PgSslMode { match ssl { true => PgSslMode::Require, false => PgSslMode::Disable, } }; let conn = PgConnectOptions::new() .host(db.host.as_str()) .port(db.port) .username(db.user.as_str()) .password(db.password.as_str()) .database(db.dbname.as_str()) // 新增该行,传入你要操作的业务库名称 .ssl_mode(from_ssl(db.ssl)); let pool = PgPoolOptions::new() .max_connections(5) .idle_timeout(Some(Duration::new(60, 0))) .connect_with(conn) .await?; Ok(DbBuilder { pool })
- (低概率排查项)如果补全库名后仍有异常,检查代码中是否存在未显式提交的事务:sqlx的事务实例如果没有调用
.commit().await就离开作用域,会自动触发回滚,也会导致数据不落地。你贴出的INSERT代码是直接通过连接池执行,单条语句默认自动提交,一般不会触发这个问题。 - 验证修复结果:插入后在同连接池执行对应条件的SELECT查询,同时确认你的数据库客户端连接的是同一个业务库,避免客户端缓存、连错实例导致的看不到数据的误判。
你贴出的INSERT语句本身没有语法问题,不需要修改:
sqlx::query!("INSERT INTO configs \ (name, is_available, membership_id, priority_index, params)\ VALUES( $1, $2 ,$3 ,$4, $5);", name, is_available, 1, 1, params) .execute(&db.pool) .await?;
内容的提问来源于stack exchange,提问作者Gleb Protasov
相关产品推荐
相关产品推荐

