我有一个 Postgres 数据库的全局实例,它在整个代码中都在使用。
有 500 个 goroutine 使用同一个实例将一些数据插入数据库。
那么当只有一个实例(客户端)时,为什么它会失败panic: FATAL #53300 sorry, too many clients already
?
我的理解是,只有一个数据库实例ConnectToDB()
在第一次调用时由方法创建,而在随后的调用中,它只是返回这个实例而不是创建一个新实例。
最后,当 main 结束时,该单个实例被关闭。
我无法理解它怎么可能创建太多的实例,如错误消息所示。
package main
import (
"github.com/go-pg/pg/v10"
"github.com/go-pg/pg/v10/orm"
"sync"
)
var db *pg.DB
var once sync.Once
type DummyTable struct {
IdOne int
IdTwo int
}
func main() {
var wg sync.WaitGroup
db := ConnectToDB()
defer db.Close()
for i := 0; i < 500; i++ {
wg.Add(1)
go insertIntoDB(&wg)
}
wg.Wait()
}
func insertIntoDB(wg *sync.WaitGroup) {
defer wg.Done()
localDb := ConnectToDB()
_, err := localDb.Model(&DummyTable{
IdOne: 2,
IdTwo: 3,
}).Insert()
if err != nil {
panic(err)
}
}
func createSchema(db *pg.DB) error {
models := []interface{}{
(*DummyTable)(nil),
}
for _, model := range models {
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
Temp: false,
})
if err != nil {
return err
}
}
return nil
}
func ConnectToDB() *pg.DB {
once.Do(func() {
db = pg.Connect(&pg.Options{
User: "username",
Database: "dbName",
})
err := createSchema(db)
if err != nil {
panic(err)
}
})
return db
}