我正在使用golang访问postgresql。 这是我的功能
for {
db, err := database.GetNewConnection(dbname)
err = db.QueryRow("SELECT COALESCE(COUNT(1),0) FROM table").Scan(&count)
if count == 0 {
var insert = "INSERT INTO table(last_update_time,next_update_time,schedule_frequency)" +
"VALUES($1,$2,$3)"
prep_ins, err := db.Prepare(insert)
if err != nil {
return
}
_, err = prep_ins.Exec(cur_time, 1464718530, 86400)
if err != nil {
return
}
defer prep_ins.Close()
defer db.Close()
} else {
var sel_str = "SELECT next_update_time FROM table"
prep_update, err := db.Prepare(sel_str)
if err != nil {
return
}
_, err = prep_update.Exec()
if err != nil {
defer prep_update.Close()
return
}
defer prep_update.Close()
defer db.Close()
}
time.Sleep(10 * 60 * time.Second)
}
每10分钟,此函数将运行并执行这些语句。它工作正常,但连接将处于空闲状态。我正在使用pg_stat_activity
进行检查,状态仅为空闲状态。每隔10分钟,就会创建一个新的连接并进入空闲状态。所以它会不断增加。我不知道为什么会这样。
提前致谢。
答案 0 :(得分:3)
for
循环是一个无限循环,它永远不会返回。这意味着永远不会执行延期,也不会关闭连接。您需要在循环结束时添加显式db.Close()
。
如果每次执行任务时都不需要新连接,也可以将db
的初始化移出循环。您只需创建一个连接并重复使用即可。如果您这样做,请在defer
的初始化下方移动db
语句。如果数据库操作返回一些错误,则延迟将关闭连接。
db, err := database.GetNewConnection(dbname)
if err != nil {
return fmt.Errorf("Error in creating database connection: %+v", err)
}
defer db.Close()
for {
// ...
db.Close()
}
通过执行此操作,您可以确保在函数的每个返回路径上关闭连接(https://blog.golang.org/defer-panic-and-recover)
如果您仍然在循环中保留db
初始化,请删除defers
,因为他们只会在显式关闭数据库连接时添加到延迟堆栈。
答案 1 :(得分:1)
正如@abhink所指出的那样,由于永远运行for
循环,因此未调用defer语句。使用for
循环计划执行一段代码的实现并不是最佳的。
您应该使用golang频道。
package main
import (
"fmt"
"time"
)
func main() {
//You can configure your tick for 10 mnts.
tick := time.Tick(100 * time.Millisecond)
//some exit condition
exit := time.After(1000 * time.Millisecond)
for {
select {
case <-tick:
poke()
case <-exit:
fmt.Println("Exit")
return
default:
fmt.Println(" .")
time.Sleep(50 * time.Millisecond)
}
}
}
func poke() {
fmt.Println("Opening connection")
defer fmt.Println("Closing connection")
fmt.Println("Inserting into Database")
}
您可以更改pock()
功能以将记录插入数据库。并且您可以配置自动收报机每10分钟打勾。由于每个tick都会触发一个新的函数调用,因此一旦pock()
函数执行完成,就会调用defer。
请参阅此操场代码段https://play.golang.org/p/1fQgbmI9LY
答案 2 :(得分:1)
defer
函数仅在函数返回时调用。在循环中,当循环处于活动状态时,defer db.Close()
永远不会执行,因此函数永远不会被调用。
您可以将for
中的逻辑包装在闭包中以实现延迟:
for{
func(){
// inner code
}()
time.Sleep(10 * 60 * time.Second)
}