我有一个通过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/