跳过正文

gorm使用问题集

·471 字
目录

gorm连接被mysql server断开
#

报错如下
#

[mysql] 2023/01/11 16:41:19 packets.go:122: closing bad idle connection: EOF 

查看MySQL服务器连接超时时间, 28800s(8小时)
#

mysql> show global variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout  | 28800 |
+---------------+-------+

连接池设置
#

默认情况下,gorm客户端最大连接时间为0,即不主动断开连接

sqlDB, err := db.DB()

// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)

// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)

// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour) // 不设置则默认为0,即客户端不断开连接

// 获取连接实例状态
sqlDB.Stats()

设置连接最大复用时间源码
#

标准库database/sql/sql.go go版本 v1.18.9

设置最大连接时间后,客户端会启动清理超时连接的协程,超时后主动断开连接

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
//
// Expired connections may be closed lazily before reuse.
//
// If d <= 0, connections are not closed due to a connection's age.
func (db *DB) SetConnMaxLifetime(d time.Duration) {
	if d < 0 {
		d = 0
	}
	db.mu.Lock()
	// Wake cleaner up when lifetime is shortened.
	if d > 0 && d < db.maxLifetime && db.cleanerCh != nil {
		select {
		case db.cleanerCh <- struct{}{}:
		default:
		}
	}
	db.maxLifetime = d
	db.startCleanerLocked()
	db.mu.Unlock()
}

解决方式
#

获取DB实例时,若实例Ping()失败则重新建立连接

更正,gorm本身维护的就是一个连接池,即使连接实例被断开也会自动重连,不需关心实例是否被断开了

var db *gorm.DB
...
func GetDB() *gorm.DB {
	sqlDB, err := db.DB()
	if err != nil {
		// do something
	}
}