如何在非常短的时间内/同时进行多个查询

15

嘿,我收到了一个错误信息:conn busy,来自pgx。

我不知道该怎么解决。这是我的函数:

func (r *proverbRepo) SelectPendingProverbs(table string) (proverbs []domain.Proverb, err error) {
    query := fmt.Sprintf("SELECT id, proverb literal FROM %s", table)
    rows, err := r.Db.Query(context.Background(), query)
    defer rows.Close()

    if err != nil {
        return
    }

    for rows.Next() {
        var prov domain.Proverb
        if err = rows.Scan(&prov.ID, &prov.Literal); err != nil {
            return
        }
        proverbs = append(proverbs, prov)
    }
    return
}

r.Dbpgx.Connect(context.Background(), os.Getenv("PSQL_URL"))

我从两个不同的前端请求中,在非常短的时间间隔内获取了两个不同的表格。

第一个请求可以顺利执行,但另一个请求会返回conn busy的错误信息。

我真的不知道该寻找什么,有人可以帮我吗?


2
建议:不要在错误检查之前延迟执行,如果 err 不为 nil,则 rows 将为 nil,由于您在错误检查之前进行了延迟执行,因此在从错误检查返回时将触发 defer,并且 Close 将在 nil rows 实例上调用。这不是一个好的做法。 - mkopriva
谢谢,虽然没有解决问题,但我已经更新了我的函数。 - Ado Ren
1
"Conn busy" 表示你在某个地方缺少了 Close 调用,可能是在程序中共享 DB 实例的其他部分中。 - Peter
好的,那么这与请求的同时性无关?我会再次检查关闭调用。 - Ado Ren
可能与上下文有关。仍在寻找。 - Ado Ren
我有类似的问题,并创建了一个工单 https://github.com/jackc/pgx/issues/1226 - Sergey Ponomarev
2个回答

16

pgx.Connect()返回一个pgx.Conn,它不能被同时使用。这是godocs中该类型的说明:

Conn是一个 PostgreSQL 连接句柄。它不适用于并发使用。使用连接池来管理对多个数据库连接的访问,以便从多个 goroutine 中进行访问。

因此,如果您将pgx.Connect()替换为来自github.com/jackc/pgx/pgxpoolpgxpool.Connect(),那么就可以了。


7
r.Db 是由 pgx.Connect(context.Background(), os.Getenv("PSQL_URL")) 返回的类型为 *pgx.Conn 的对象,它代表一个不支持并发的单个连接。通常情况下,你会想要使用连接池来处理并发,并允许重用已打开的连接。 要使用连接池,请将 import github.com/jackc/pgx/v4 替换为 github.com/jackc/pgx/v4/pgxpool ,并使用 pgxpool.Connect() 而不是 pgx.Connect() 进行连接,API 不会有变化:
r.Pool := pgxpool.Connect(context.Background(), os.Getenv("PSQL_URL"))
r.Pool.Query(context.Background(), query)
...

如果您需要在任何时候使用单个连接来访问某些低级别的功能,您可以按以下方式安全地获取并发安全连接:

conn, err := r.Pool.Acquire(context.Background())
if err != nil {
    fmt.Fprintln(os.Stderr, "Error acquiring connection:", err)
    os.Exit(1)
}
defer conn.Release()
...

3
感谢您的完整回答。只有一个问题,为什么他们在文档中没有提及这个问题,我们不是总是同时连接到数据库吗?为什么它被设计为单连接API? @DhiaTN - Aliy
@Aliy 完全同意。最好坚持使用标准包以避免未来出现此类错误。 - Jessica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接