Skip to content

GitLab

  • Menu
Projects Groups Snippets
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • V verify
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 22
    • Issues 22
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Packages & Registries
    • Packages & Registries
    • Package Registry
    • Container Registry
    • Infrastructure Registry
  • Analytics
    • Analytics
    • CI/CD
    • Repository
    • Value stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • ran.lu
  • verify
  • Issues
  • #22

Closed
Open
Created Mar 01, 2023 by ran.lu@ran.luMaintainer

达梦连接断开后重试

问题现象

以 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:

image

所以,一个想法是,把特定的错误,改写为 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)除了查询,还有执行,也得处理一下。

Edited Mar 01, 2023 by ran.lu
Assignee
Assign to
Time tracking