达梦连接断开后重试
问题现象
以 ai-arts 为例。
ai-arts 启动后, 自已会不断查库. 比如, 它会定时查 projects.
ai-arts 连接上 dameng 后,关闭 dameng ; 一段时间后, 又重开 dameng, 观察 ai-arts 的数据库查询状态。
预期: ai-arts 能重新连上 dameng;
实际: ai-arts 持续报错
思路
观察 ai-arts 定时查 projects.
首先,有个问题,为什么 postgres 可以作到自动重连.
有关机制,可以从这一段代码 go sdk sql/sql.go 中发现:
// QueryContext executes a query that returns rows, typically a SELECT.
// The args are for any placeholder parameters in the query.
func (db *DB) QueryContext(ctx context.Context, query string, args ...any) (*Rows, error) {
var rows *Rows
var err error
var isBadConn bool
for i := 0; i < maxBadConnRetries; i++ {
rows, err = db.query(ctx, query, args, cachedOrNewConn)
isBadConn = errors.Is(err, driver.ErrBadConn)
if !isBadConn {
break
}
}
if isBadConn {
return db.query(ctx, query, args, alwaysNewConn)
}
return rows, err
}
也就是说,如果下层返回了 driver.ErrBadConn , isBadConn 就会是 true , 就会不断重试。
而实际上, dm 返回的是 dm.DmError:
所以,一个想法是,把特定的错误,改写为 driver.ErrBadConn 。其中的 ErrCode ,有助于我们这么做。
这种改写,虽然不太好,但是有人已经这么做了. 比如 pkg\mod\github.com\jackc\pgx\v5@v5.2.0\stdlib\sql.go :
func (c *Conn) ResetSession(ctx context.Context) error {
if c.conn.IsClosed() {
return driver.ErrBadConn
}
now := time.Now()
if now.Sub(c.lastResetSessionTime) > time.Second {
if err := c.conn.PgConn().CheckConn(); err != nil {
return driver.ErrBadConn
}
}
c.lastResetSessionTime = now
return c.resetSessionFunc(ctx, c.conn)
}
代码变更
目前已经尝试了这样的变更: https://gitlab.apulis.com.cn/sdk/gorm-extension/-/merge_requests/1/diffs
在 ai-arts 上使用,可以让它的定时查询,在 dameng 重启后,恢复正常。
不过,这只是数据查询的情况: 1)查询的其它入口,可能也得加一个这个改写; 2)除了查询,还有执行,也得处理一下。