Search code examples
gogo-gorm

What is the best way to use gorm in multithreaded application?


I have an application that opens a lot routines. Lets say 2000 routines. Each routine needs access to DB, or at least needs update/select data from DB.

My current approach is the following:

Routine gets *gorm.DB with db.GetConnection(), this is the code of this function:

func GetConnection() *gorm.DB {
    DBConfig := config.GetConfig().DB
    db, err := gorm.Open("mysql", DBConfig.DBUser+":"+DBConfig.DBPassword+"@/"+DBConfig.DBName+"?charset=utf8mb4")
    if err != nil {
        panic(err.Error())
    }
    return db
}

then routines calls another function from some storage package and passes *gorm.DB to function and closes the connection, it looks like that:

dbConnection := db.GetConnection()
postStorage.UpdateSomething(dbConnection)
db.CloseConnection(dbConnection)

The above is only example, the main idea is that each routine opens new connection and I don't like it. Because it may overload the DB. In result I got the next MySQL error:

[mysql] 2020/07/16 19:34:26 packets.go:37: read tcp 127.0.0.1:44170->127.0.0.1:3306: read: connection reset by peer

The question is about good pattern how to use gorm package in multiroutines application ?


Solution

  • *gorm.DB is multi thread safe, and you could use one *gorm.DB in multi routines. You could init it once and get it whenever you want. Demo:

    package db
    
    var db *gorm.DB
    
    func init() {
        DBConfig := config.GetConfig().DB
        db, err := gorm.Open("mysql", DBConfig.DBUser+":"+DBConfig.DBPassword+"@/"+DBConfig.DBName+"?charset=utf8mb4")
        if err != nil {
            panic(err.Error())
        }
    }
    
    func GetConnection() *gorm.DB {
        return db;
    }