文章目录
- 连接失效自动重试 如果驱动返回 ErrBadConn,database/sql 会自动重试操作 连接池会自动检测并移除失效的连接 下次使用时,会从连接池获取新连接(如果连接池中有可用连接) 连接池自动补充 当连接池中的连接失效时,会在需要时自动创建新连接 只要 sql.DB 对象没有被关闭,连接池会持续工作
- 整个连接池被关闭 如果调用了 db.Close(),整个连接池被关闭 不会自动重新打开,需要重新创建 sql.DB 对象 长时间停机后的恢复 如果 MySQL 停机时间很长,连接池中的所有连接都可能失效 虽然连接池会尝试创建新连接,但没有主动的健康检查 只有在实际使用时才会发现连接失效并重试
- // 程序已连接 db, _ := sql.Open(“mysql”, “dsn…”) // MySQL 停机 // … MySQL 重启 … // 下次使用时 rows, err := db.Query(“SELECT * FROM users”) // ✅ 可能成功:如果连接池中有可用连接,会自动重试 // ⚠️ 可能失败:如果所有连接都失效,需要等待重试或手动处理 行为: database/sql 会检测到连接失效(返回 ErrBadConn) 自动重试操作,尝试从连接池获取新连接 如果连接池中有可用连接,会成功 如果所有连接都失效,会创建新连接
- // 程序已连接 db, _ := sql.Open(“mysql”, “dsn…”) // MySQL 长时间停机 // … 所有连接都失效 … // MySQL 重启后 rows, err := db.Query(“SELECT * FROM users”) // ⚠️ 第一次调用可能失败,需要重试 // ✅ 后续调用会成功(连接池已恢复) 行为: 连接池中的所有连接都已失效 第一次调用时,会尝试使用失效的连接,失败 database/sql 检测到 ErrBadConn,自动重试 重试时会创建新连接,成功
- // 程序已连接 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 错误 不会自动重新打开
- 原生机制通常足够: db, _ := sql.Open(“mysql”, “dsn…”) // 不需要特殊处理,database/sql 会自动处理连接失效
- 建议添加重试逻辑: 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) }
- 原生机制不支持: db.Close() // ❌ 无法恢复,需要重新创建
目录
- 1. 连接池的自动管理
- ✅ 支持的情况
- ❌ 不支持的情况
- 2. 实际场景分析
- 场景1: MySQL 短暂停机(几秒到几分钟)
- 场景2: MySQL 长时间停机(几分钟到几小时)
- 场景3: 调用 db.Close() 后
- 实际使用建议
- 1. 对于 MySQL 短暂停机
- 2. 对于 MySQL 长时间停机
- 3. 对于需要 Close() 的场景
- 总结
Go 的 database/sql 包确实有部分自动重连能力,但有限制:
-
连接失效自动重试
- 如果驱动返回
ErrBadConn,database/sql 会自动重试操作
- 连接池会自动检测并移除失效的连接
- 下次使用时,会从连接池获取新连接(如果连接池中有可用连接)
-
连接池自动补充
- 当连接池中的连接失效时,会在需要时自动创建新连接
- 只要
sql.DB 对象没有被关闭,连接池会持续工作
连接失效自动重试
- 如果驱动返回
ErrBadConn,database/sql会自动重试操作 - 连接池会自动检测并移除失效的连接
- 下次使用时,会从连接池获取新连接(如果连接池中有可用连接)
连接池自动补充
- 当连接池中的连接失效时,会在需要时自动创建新连接
- 只要
sql.DB对象没有被关闭,连接池会持续工作
-
整个连接池被关闭
- 如果调用了
db.Close(),整个连接池被关闭
- 不会自动重新打开,需要重新创建
sql.DB 对象
-
长时间停机后的恢复
- 如果 MySQL 停机时间很长,连接池中的所有连接都可能失效
- 虽然连接池会尝试创建新连接,但没有主动的健康检查
- 只有在实际使用时才会发现连接失效并重试
整个连接池被关闭
- 如果调用了
db.Close(),整个连接池被关闭 - 不会自动重新打开,需要重新创建
sql.DB对象
长时间停机后的恢复
- 如果 MySQL 停机时间很长,连接池中的所有连接都可能失效
- 虽然连接池会尝试创建新连接,但没有主动的健康检查
- 只有在实际使用时才会发现连接失效并重试
// 程序已连接
db, _ := sql.Open("mysql", "dsn...")
// MySQL 停机
// ... MySQL 重启 ...
// 下次使用时
rows, err := db.Query("SELECT * FROM users")
// ✅ 可能成功:如果连接池中有可用连接,会自动重试
// ⚠️ 可能失败:如果所有连接都失效,需要等待重试或手动处理
行为:
database/sql会检测到连接失效(返回ErrBadConn)- 自动重试操作,尝试从连接池获取新连接
- 如果连接池中有可用连接,会成功
- 如果所有连接都失效,会创建新连接
// 程序已连接
db, _ := sql.Open("mysql", "dsn...")
// MySQL 长时间停机
// ... 所有连接都失效 ...
// MySQL 重启后
rows, err := db.Query("SELECT * FROM users")
// ⚠️ 第一次调用可能失败,需要重试
// ✅ 后续调用会成功(连接池已恢复)
行为:
- 连接池中的所有连接都已失效
- 第一次调用时,会尝试使用失效的连接,失败
database/sql检测到ErrBadConn,自动重试- 重试时会创建新连接,成功
// 程序已连接
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错误 - 不会自动重新打开
原生机制通常足够:
db, _ := sql.Open("mysql", "dsn...")
// 不需要特殊处理,database/sql 会自动处理连接失效
建议添加重试逻辑:
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)
}
原生机制不支持:
db.Close() // ❌ 无法恢复,需要重新创建
database/sql 原生机制:
- ✅ 处理连接失效和自动重试
- ✅ 连接池自动管理
- ❌ 不支持 Close() 后恢复
- ❌ 没有主动健康检查
到此这篇关于golang 原生databasesql 的重连机制实现的文章就介绍到这了,更多相关golang 重连机制内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- 关于golang监听rabbitmq消息队列任务断线自动重连接的问题
- golang之tcp自动重连实现方法