英文:
Golang transaction exit handling
问题
我有一个每秒大约100个请求的系统。有时候,直到我重新启动我的Go程序,它才会响应。我发现这是因为我在某些地方打开了事务但没有关闭它。这就是为什么所有的连接都被打开的事务占用,我无法打开另一个事务。为了解决这个问题,我添加了以下代码:
defer func() {
if r := recover(); r != nil {
tx.Rollback()
return
}
if err == nil {
err = tx.Commit()
} else {
tx.Rollback()
}
}()
这使得我的程序可以连续工作一个月而没有中断。但刚刚又发生了同样的问题。可能是因为这个问题。有没有更好的方法来关闭事务?或者有没有一种方法在事务打开了1分钟后自动关闭它?
英文:
I have a system with about 100 req/sec. And sometimes it doesn't respond until I restart my go program. I found out that this is because I open transaction and don't close it in some places. That's why all connections were occupied by opened transactions and I couldn't open another one After this I added this code
defer func() {
if r := recover(); r != nil {
tx.Rollback()
return
}
if err == nil {
err = tx.Commit()
} else {
tx.Rollback()
}
}()
This made my program work for a month without interruption. But just now it happened again. Probably because of this issue. Is there a better way to close transaction? Or maybe a way to close a transaction if it was open for 1 minute?
答案1
得分: 2
如果您想在1分钟后回滚事务,可以使用标准的Go超时模式(如下所示)。
然而,可能有更好的方法来处理您的问题。您没有提供太多关于问题的信息,但您可能正在使用带有上下文的标准HTTP请求。在这种情况下,您可能会发现,当上下文被取消时,在上下文中启动的事务会自动回滚。确保如果某些操作被卡住,上下文会被取消的一种方法是给它一个截止时间。
> 摘自Channels - Timeouts。原作者是Chris Lucas、Kwarrtz和Rodolfo Carvalho。有关归属详细信息,请参见贡献者页面。该来源采用CC BY-SA 3.0许可,可在文档存档中找到。参考主题ID:1263,示例ID:6050。
超时
通常使用通道来实现超时。
func main() {
// 创建一个带缓冲的通道以防止goroutine泄漏。缓冲区确保下面的goroutine最终可以终止,即使超时已经到达。如果没有缓冲区,通道上的发送操作将永远阻塞,等待永远不会发生的读取,从而导致goroutine泄漏。
ch := make(chan struct{}, 1)
go func() {
time.Sleep(10 * time.Second)
ch <- struct{}{}
}()
select {
case <-ch:
// 在超时之前完成的工作。
case <-time.After(1 * time.Second):
// 在1秒后工作未完成。
}
}
英文:
If you want to roll back the transaction after 1 minute, you can use the standard Go timeout pattern (below).
However, there may be better ways to deal with your problems. You don’t give a lot of information about it, but you are probably using standard HTTP requests with contexts. In that case, it may help you to know that a transaction started within a context is automatically rolled back when the context is cancelled. One way to make sure that a context is cancelled if something gets stuck is to give it a deadline.
> Excerpted from Channels - Timeouts. The original authors were Chris Lucas, Kwarrtz and Rodolfo Carvalho. Attribution details can be found on the contributor page. The source is licenced under CC BY-SA 3.0 and may be found in the Documentation archive. Reference topic ID: 1263 and example ID: 6050.
Timeouts
Channels are often used to implement timeouts.
func main() {
// Create a buffered channel to prevent a goroutine leak. The buffer
// ensures that the goroutine below can eventually terminate, even if
// the timeout is met. Without the buffer, the send on the channel
// blocks forever, waiting for a read that will never happen, and the
// goroutine is leaked.
ch := make(chan struct{}, 1)
go func() {
time.Sleep(10 * time.Second)
ch <- struct{}{}
}()
select {
case <-ch:
// Work completed before timeout.
case <-time.After(1 * time.Second):
// Work was not completed after 1 second.
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论