Как лучше всего использовать gorm в многопоточном приложении?

У меня есть приложение, которое открывает множество подпрограмм. Допустим, 2000 процедур. Каждая процедура требует доступа к БД или, по крайней мере, требует обновления / выбора данных из БД.

Мой текущий подход следующий:

Подпрограмма получает *gorm.DB с db.GetConnection(), это код этой функции:

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
}

затем подпрограммы вызывают другую функцию из некоторого пакета хранилища и передают *gorm.DB в функцию и закрывают соединение, это выглядит так:

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

Выше приведен только пример, основная идея заключается в том, что каждая процедура открывает новое соединение, и мне это не нравится. Потому что это может перегрузить БД. В результате я получил следующую ошибку MySQL:

[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

Вопрос в хорошем шаблоне, как использовать gorm пакет в многопрограммном приложении?


person Mikael    schedule 16.07.2020    source источник


Ответы (1)


*gorm.DB является многопоточным, и вы можете использовать один *gorm.DB в нескольких подпрограммах. Вы можете запустить его один раз и получить, когда захотите. Демо:

package db

var db *gorm.DB

fund 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;
}
person hyz    schedule 17.07.2020
comment
Спасибо! Но если я запускаю его один раз при запуске приложения, как я могу сохранить его в рабочем состоянии? Потому что приложение всегда запущено. И я думаю, что через какое-то время без запросов mysql закроет соединение, а затем, когда приложение сделает запрос - я получу ошибку .. Пожалуйста, поясните этот момент - person Mikael; 17.07.2020
comment
@Mikael Это зависит от импортируемого драйвера и database/sql. Например, github.com/go-sql-driver/mysql - это MySQL- Драйвер для Go's database/sql. По умолчанию это поможет вам поддерживать пул соединений, делать что-то вроде поддержания соединения в рабочем состоянии, масштабирования под нагрузкой (когда многие горутины активно используют базу данных) и сжатия при неактивном состоянии. Так что вам, возможно, не стоит об этом беспокоиться. - person hyz; 17.07.2020
comment
спасибо, очень полезно! Извините, еще один вопрос, нужно ли закрывать соединение? Я пробовал *gorm.DB.Close(), но потом другие программы говорят, что соединение закрыто. - person Mikael; 17.07.2020
comment
@Mikael О последнем вопросе в комментарии, если вы этого не сделаете, и в случае, если ваше приложение неожиданно прервалось (например, было убито), то это зависит от сервера базы данных, как долго соединение может простаивать перед закрытием, вы можете настроить свой сервер базы данных на такое поведение. - person user218867; 31.03.2021