我使用golang编写了一个Web应用程序。当它在生产中运行时,有一些goroutine被阻止。以下是信息(使用pprof
生成):
goroutine 792247 [chan receive, 948 minutes]:
database/sql.(*Tx).awaitDone(0xc4206e2b80)
/usr/local/go/src/database/sql/sql.go:1440 +0x57
created by database/sql.(*DB).begin
/usr/local/go/src/database/sql/sql.go:1383 +0x274
goroutine一直在等待948分钟的频道。显然,有些不对劲。但堆栈跟踪似乎不完整。我发现这个bug是不够的。 (我希望从我的程序开始一些堆栈跟踪。)
如何获得此goroutine的完整堆栈跟踪? 或者还有其他方法可以调试此问题吗?
更新:
我已经阅读了database / sql / sql.go的源代码。事实证明database/sql/sql.go:1440
是一个新的goroutine。堆栈跟踪为incomplete
,因为先前的堆栈跟踪属于parent
goroutine。
我的问题应该是:有没有更好的方法来调试这个问题?
答案 0 :(得分:0)
我认为没有任何方法可以获取父goroutine堆栈,而无需手动跟踪每个go例程调用并为其生成id。
在这种特定情况下,您可能会有一个未提交或回滚的事务,因为发生错误并且函数过早退出而没有调用。
避免相同的一个好模板是使用'延迟'。
func (s Service) DoSomething() (err error) {
tx, err := s.db.Begin()
if err != nil {
return
}
defer func() {
if err != nil {
tx.Rollback()
return
}
err = tx.Commit()
}()
if _, err = tx.Exec(...); err != nil {
return
}
if _, err = tx.Exec(...); err != nil {
return
}
// ...
return }
PS:小心错误阴影。