我有一个通过golang编写的服务,它作为使用者工作,它从kafka的队列中获取数据并将其存储在PostgreSQL数据库中。当执行某些请求时,golang开始增加PG连接数,然后超过它们的限制。我不知道为什么,请帮助我解决这个问题。
这是代码:

func SaveMessageStatus(msg models.Message) error {

db := GetPostgreInstance() // Get *sql.DB instance

// Проверяем есть ли записи

rows, err := db.Query(`select * from "tNotifStatus" where "NotificationId" = $1`, msg.NotificationID)

if err != nil {
    CheckError(err, "SLCT status", "")
    return err
}

if rows.Next() {
    // Смотрим если запись в таблице уже есть, тогда просто обновляем статусы по сообщению
    fsql := `update "tNotifStatus" set "Status" = $1, "Error" = $2, "UpdateTime" = $3 where "NotificationId" = $4`

    _, err = db.Exec(fsql, msg.Status, msg.Error, msg.UpdateTime, msg.NotificationID)

    if err != nil {
        //Логируем
        CheckError(err, "UPDT status", "")
        return err
    }

} else {
    // Если записей нет, то создаем новую
    fsql := `insert into "tNotifStatus" values ($1,$2,$3,$4,$5)`
    _, err = db.Exec(fsql, msg.NotificationID, msg.Status, msg.Error, msg.ChannelName, msg.UpdateTime)
    if err != nil {
        //Логируем
        CheckError(err, "INS status", "")
        return err
    }
}
return err

}

如果看到PG管理员监视,我们有很多新连接:

6460 UCS ucs 10.3.40.20 2018-12-27 09:35:14 +06空闲客户端:ClientRead
46462 UCS ucs 10.3.40.20 2018-12-27 09:35:17 +06空闲客户端:ClientRead
46463 UCS UCS 10.3.40.20 2018-12-27 09:35:17 +06空闲客户端:ClientRead
46517 UCS UCS 10.3.40.20 2018-12-27 09:36:20 +06空闲客户端:ClientRead
46518 UCS ucs 10.3.40.20 2018-12-27 09:36:21 +06空闲客户端:ClientRead
46520 UCS ucs 10.3.40.20 2018-12-27 09:36:22 +06空闲客户端:ClientRead
46521 UCS UCS 10.3.40.20 2018-12-27 09:36:23 +06空闲客户端:ClientRead
46522 UCS ucs 10.3.40.20 2018-12-27 09:36:23 +06空闲客户端:ClientRead
46524 UCS ucs 10.3.40.20 2018-12-27 09:36:24 +06空闲客户端:ClientRead
46525 UCS UCS 10.3.40.20 2018-12-27 09:36:24 +06空闲客户端:ClientRead
46527 UCS UCS 10.3.40.20 2018-12-27 09:36:25 +06空闲客户端:ClientRead
46529 UCS UCS 10.3.40.20 2018-12-27 09:36:25 +06空闲客户端:ClientRead
46531 UCS ucs 10.3.40.20 2018-12-27 09:36:26 +06空闲客户端:ClientRead
46532 UCS ucs 10.3.40.20 2018-12-27 09:36:26 +06空闲客户端:ClientRead
46534 UCS UCS 10.3.40.20 2018-12-27 09:36:27 +06空闲客户端:ClientRead

他们都试图执行
select * from "tNotifStatus" where "NotificationId" = $1

可能与等待事件(ClientRead)有关,golang lib启动了新连接,而旧连接仍在尝试完成“SELECT”

这是连接到数据库的代码
    func GetPostgreInstance() *sql.DB {
    return postgreClient
}

func InitPqConnection() {

    var err error

    var configuration models.Configuration
    configuration.Load()

    connStr := configuration.PostgreConnString

    postgreClient, err = sql.Open("postgres", connStr)
    if err != nil {
        CheckError(err, "Connection to db", "")
        panic("Error connection to DB")
    }
    fmt.Println("Connected to db")
}

最佳答案

您需要使用QueryRow(),因为您既不使用也不希望有多行,或者需要执行defer rows.Close()(使用.Query时应始终这样做

https://golang.org/pkg/database/sql/#Rows.Close

Close关闭行,防止进一步枚举。如果调用Next并返回false,并且没有其他结果集,则将自动关闭行,这将足以检查Err的结果。关闭是幂等的,不会影响Err的结果。

http://go-database-sql.org/retrieving.html

如果出于某种原因退出循环(提前返回等),则行不会关闭,连接保持打开状态。

rows, err := db.Query(`select * from "tNotifStatus" where "NotificationId" = $1`, msg.NotificationID)
if err != nil {
    CheckError(err, "SLCT status", "")
    return err
}
defer rows.Close()

由于您甚至没有迭代rows.Next(),因此您基本上不会达到自动关闭条件,并且始终保持连接打开。

关于postgresql - 微服务成倍增加postgres连接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53939911/

10-14 18:51