golang 原生database\sql 的重连机制实现
作者:落舞者
本文主要介绍了golang 原生database\sql 的重连机制实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
1. 连接池的自动管理
Go 的 database/sql 包确实有部分自动重连能力,但有限制:
✅ 支持的情况
连接失效自动重试
- 如果驱动返回
ErrBadConn,database/sql会自动重试操作 - 连接池会自动检测并移除失效的连接
- 下次使用时,会从连接池获取新连接(如果连接池中有可用连接)
- 如果驱动返回
连接池自动补充
- 当连接池中的连接失效时,会在需要时自动创建新连接
- 只要
sql.DB对象没有被关闭,连接池会持续工作
❌ 不支持的情况
整个连接池被关闭
- 如果调用了
db.Close(),整个连接池被关闭 - 不会自动重新打开,需要重新创建
sql.DB对象
- 如果调用了
长时间停机后的恢复
- 如果 MySQL 停机时间很长,连接池中的所有连接都可能失效
- 虽然连接池会尝试创建新连接,但没有主动的健康检查
- 只有在实际使用时才会发现连接失效并重试
2. 实际场景分析
场景1: MySQL 短暂停机(几秒到几分钟)
// 程序已连接
db, _ := sql.Open("mysql", "dsn...")
// MySQL 停机
// ... MySQL 重启 ...
// 下次使用时
rows, err := db.Query("SELECT * FROM users")
// ✅ 可能成功:如果连接池中有可用连接,会自动重试
// ⚠️ 可能失败:如果所有连接都失效,需要等待重试或手动处理
行为:
database/sql会检测到连接失效(返回ErrBadConn)- 自动重试操作,尝试从连接池获取新连接
- 如果连接池中有可用连接,会成功
- 如果所有连接都失效,会创建新连接
场景2: MySQL 长时间停机(几分钟到几小时)
// 程序已连接
db, _ := sql.Open("mysql", "dsn...")
// MySQL 长时间停机
// ... 所有连接都失效 ...
// MySQL 重启后
rows, err := db.Query("SELECT * FROM users")
// ⚠️ 第一次调用可能失败,需要重试
// ✅ 后续调用会成功(连接池已恢复)
行为:
- 连接池中的所有连接都已失效
- 第一次调用时,会尝试使用失效的连接,失败
database/sql检测到ErrBadConn,自动重试- 重试时会创建新连接,成功
场景3: 调用 db.Close() 后
// 程序已连接
db, _ := sql.Open("mysql", "dsn...")
// 关闭连接池
db.Close()
// 尝试使用
rows, err := db.Query("SELECT * FROM users")
// ❌ 失败:sql: database is closed
// ❌ 不会自动重连,需要重新创建 sql.DB 对象
行为:
sql.DB对象被标记为已关闭- 所有操作都会返回
sql: database is closed错误 - 不会自动重新打开
实际使用建议
1. 对于 MySQL 短暂停机
原生机制通常足够:
db, _ := sql.Open("mysql", "dsn...")
// 不需要特殊处理,database/sql 会自动处理连接失效
2. 对于 MySQL 长时间停机
建议添加重试逻辑:
db, _ := sql.Open("mysql", "dsn...")
// 添加重试逻辑
var rows *sql.Rows
var err error
for i := 0; i < 3; i++ {
rows, err = db.Query("SELECT * FROM users")
if err == nil {
break
}
time.Sleep(time.Second)
}
3. 对于需要 Close() 的场景
原生机制不支持:
db.Close() // ❌ 无法恢复,需要重新创建
总结
database/sql 原生机制:
- ✅ 处理连接失效和自动重试
- ✅ 连接池自动管理
- ❌ 不支持 Close() 后恢复
- ❌ 没有主动健康检查
到此这篇关于golang 原生database\sql 的重连机制实现的文章就介绍到这了,更多相关golang 重连机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
