Golang事务退出处理

huangapple go评论92阅读模式
英文:

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 LucasKwarrtzRodolfo 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 &lt;- struct{}{}
    }()

    select {
    case &lt;-ch:
        // Work completed before timeout.
    case &lt;-time.After(1 * time.Second):
        // Work was not completed after 1 second.
    }
}

huangapple
  • 本文由 发表于 2017年3月20日 00:45:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/42889249.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定