2

我有一个 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
}

4

0 回答 0