Go处理数据库错误需区分错误类型:连接类、锁超时等可重试,主键冲突、事务异常等不可重试;应使用驱动提供的错误谓词函数精准判断,并实施最多3次指数退避重试。

Go 语言中处理数据库错误,关键不是“捕获所有 error”,而是识别错误类型、区分可恢复与不可恢复错误,并对网络抖动、锁冲突等常见临时性问题实施有节制的重试。直接 if err != nil { log.Fatal(err) } 在生产环境极易导致服务雪崩。
Go 的 database/sql 本身不定义具体错误码,实际错误来自底层驱动(如 github.com/lib/pq、github.com/go-sql-driver/mysql)。需按驱动文档解析错误细节:
dial tcp: i/o timeout、connection refused、server closed —— 属于临时性故障,适合重试23505,MySQL 的 1062)、外键约束失败(23503)、空值违例(23502)—— 逻辑错误,重试无意义,应修正输入或业务逻辑55P03(lock_not_*ailable),MySQL 的 1205(deadlock)或 1206(lock_wait_timeout)—— 可重试,但需退避pq: current transaction is aborted, commands ignored until end of transaction block —— 必须回滚后新建事务,不能继续执行避免字符串匹配,优先使用驱动提供的错误检查函数:
import "github.com/lib/pq"
<p>func isUniqueViolation(err error) bool {
if pqErr, ok := err.(*pq.Error); ok {
return pqErr.Code == "23505"
}
return false
}</p><p>func isLockTimeout(err error) bool {
if pqErr, ok := err.(*pq.Error); ok {
return pqErr.Code == "55P03"
}
return false
}</p><p>func isNetworkError(err error) bool {
return strings.Contains(err.Error(), "i/o timeout") ||
strings.Contains(err.Error(), "
connection refused") ||
strings.Contains(err.Error(), "broken pipe") ||
errors.Is(err, io.EOF)
}
MySQL 驱动也提供类似能力:mysql.MySQLError 结构体含 Number 字段,可直接比对错误码(如 err.Number == 1062)。
立即学习“go语言免费学习笔记(深入)”;
重试不是越多越好。推荐最多 3 次,配合指数退避(如 100ms → 300ms → 900ms),并排除不可重试错误:
晓象AI资讯阅读神器
晓象-AI时代的资讯阅读神器
72
查看详情
func withRetry(fn func() error, maxRetries int) error {
var err error
for i := 0; i <= maxRetries; i++ {
err = fn()
if err == nil {
return nil
}
if !shouldRetry(err) {
return err // 不该重试,立即返回
}
if i < maxRetries {
d := time.Duration(math.Pow(3, float64(i))) * time.Millisecond * 100
time.Sleep(d)
}
}
return err
}
<p>func shouldRetry(err error) bool {
return isNetworkError(err) || isLockTimeout(err)
}
注意:不要在事务内部盲目重试整个事务块 —— 若已执行部分语句,重试可能造成重复写入。应在事务外重试“事务函数”本身。
数据库错误不应透传给前端。建议统一转换为业务错误码和提示:
可用简单错误包装器实现:
type AppError struct {
Code int
Message string
Err error
}
<p>func (e <em>AppError) Error() string { return e.Message }
func (e </em>AppError) Unwrap() error { return e.Err }
基本上就这些。核心是分清错误性质:临时的就等一等再试,逻辑错的就别硬刚,网络断的就重连,约束炸的就改数据。不复杂但容易忽略。
以上就是如何在Golang中处理数据库错误_Golang SQL错误分类与重试策略的详细内容,更多请关注其它相关文章!
相关文章:
深入理解J*aScript中的B样条曲线与节点向量生成
漫蛙manwa官网登录界面_漫蛙漫画网页版主站入口
解决PHP集成HTML后CSS和图片路径加载问题的指南
支付宝碰一碰设备是REDMI手机吗 博主拆机辟谣:处理器、内存都不一样
Win10怎么制作U盘启动盘 Win10系统安装U盘制作教程【详解】
b站怎么看视频的弹幕数量_b站弹幕数量查看方法
PHP表单提交消息延迟显示:Post-Redirect-Get模式深度解析与实践
夸克浏览器网页版最新地址 夸克浏览器官方入口合集
mcjs网页版流畅运行 mcjs低配电脑畅玩入口
uc浏览器网页版入口 uc浏览器网页版最新网址
解决Bootstrap卡片顶部边距导致背景图下移的问题
AO3网页版合集入口 Archive of Our Own同人作品浏览指南
Lar*el Form Request 中唯一性验证更新操作的正确实践
解决 Vaadin 8 中大文件音频播放与定位时出现的 IOException
html5 app怎么运行环境_配html5 app运行环境【教程】
Go调试环境为何无法启动_Go调试器启动失败原因与解决策略
J*a ArrayList索引越界异常:动态构建列数据的高效策略
Selenium Python中处理点击后新窗口加载冻结问题的策略与实践
J*a递归快速排序中静态变量的状态管理与陷阱
Composer如何处理Git子模块(submodule)依赖_Composer与Git Submodule的对比与选择
如何在Promise链中有效终止错误处理后的执行
优化Lar*el Docker镜像:Composer与PHP版本控制策略
J*a TimerTask文件监控:HashMap状态管理与常见陷阱规避指南
蛙漫正版漫画平台入口_蛙漫免费阅读全站漫画资源
PHP基于会话的用户类型页面访问控制指南
如何在离线环境中使用Composer_Composer离线安装依赖包的技巧与策略
PyTorch模型训练效果不佳?深入剖析常见错误与调试技巧
J*aScript数组对象转换:按指定键分组与值收集
铁路12306改签能改到更早的车次吗_铁路12306改签提前车次规则
PHP面向对象编程中避免重复创建PDO数据库连接的最佳实践
Typer应用中动态命令行参数的解析与处理
写好的html代码怎么运行出来_运行写好的html代码方法【教程】
163邮箱注册官网 免费申请163个人邮箱
铁路12306卧铺选择攻略 铁路12306下铺座位预定技巧
在J*a中如何实现对象克隆避免共享数据_对象克隆安全实践指南
美团外卖商家服务中心入口 美团商家版官网入口
Win10磁盘清理工具在哪 Win10打开并使用磁盘清理【教程】
Angular Material 垂直步进器:实现底部到顶部排序的教程
如何在PHP中实现基于MySQL的动态分页查询
如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置
J*aScript中localStorage数据的获取、清洗与格式化教程
在J*a中如何使用Stream.map转换元素_Stream映射操作解析
2026年CSGO开箱网站推荐 CSGO开箱平台精选
邮政快递单号查询入口 邮政快递物流信息在线查询入口
汽车之家官方网站官网入口_汽车之家网页版直接进入
如何优雅地扩展SprykerGlue后端API授权逻辑,使用spryker/glue-backend-api-application-authorization-connector-extension
Kafka Streams中基于消息头条件过滤消息的实现指南
汽水音乐网页版使用入口_汽水音乐电脑版播放指南
SteamMachine定价或为699美元 大家想入手吗?
J*aScript Promise链中如何正确终止后续.then执行并处理错误