栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Goroutines阻止了连接池

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Goroutines阻止了连接池

你有一个僵局。在最坏的情况下,您有15个goroutine持有15个数据库连接,而所有这15个goroutine都需要一个新的连接才能继续。但是要获得新的连接,就必须前进并释放一个连接:死锁。

链接的维基百科文章详细介绍了防止死锁的方法。例如,代码执行仅在拥有需要(或将要使用)的所有资源时才进入关键部分(锁定资源)。在这种情况下,这意味着您将必须保留2个连接(恰好2个;如果只有1个可用,请保留并等待),如果您有2个,则仅继续进行查询。但是在Go中,您无法提前保留连接。在执行查询时,将根据需要分配它们。

通常应避免这种模式。您不应该编写首先保留(有限)资源(在这种情况下为db连接)的代码,然后再释放它,它需要另一个资源。

一个简单的解决方法是执行第一个查询,将其结果保存(例如保存到Go切片中),完成后再进行后续查询(但也不要忘记先关闭

sql.Rows
)。这样,您的代码不需要同时连接2个连接。

并且不要忘记处理错误!为了简洁起见,我省略了它们,但是您不应在代码中使用它们。

它看起来像这样:

go func() {    defer wg.Done()    rows, _ := db.Query("SELECt * FROM reviews LIMIT 1")    var data []int // Use whatever type describes data you query    for rows.Next() {        var something int        rows.Scan(&something)        data = append(data, something)    }    rows.Close()    for _, v := range data {        // You may use v as a query parameter if needed        db.Exec("SELECt * FROM reviews LIMIT 1")    }}()

请注意,

rows.Close()
应将其作为
defer
语句执行,以确保它将被执行(即使出现紧急情况)。但是,如果仅使用
deferrows.Close()
,则仅在执行后续查询后才执行,因此不会防止死锁。因此,我将其重构为在另一个可以使用的函数(可能是匿名函数)中调用它
defer

    rows, _ := db.Query("SELECt * FROM reviews LIMIT 1")    var data []int // Use whatever type describes data you query    func() {        defer rows.Close()        for rows.Next() { var something int rows.Scan(&something) data = append(data, something)        }    }()

还要注意,在第二个

for
循环中,由捕获的prepared语句(
sql.Stmt
DB.Prepare()
可能是执行多次相同(参数化)查询的更好选择。

另一个选择是在新的goroutine中启动后续查询,以便在释放当前锁定的连接(或任何其他goroutine锁定的任何其他连接)时发生在其中执行的查询,但是如果没有显式同步,您将无法控制何时他们被处决了。它可能看起来像这样:

go func() {    defer wg.Done()    rows, _ := db.Query("SELECt * FROM reviews LIMIT 1")    defer rows.Close()    for rows.Next() {        var something int        rows.Scan(&something)        // Pass something if needed        go db.Exec("SELECt * FROM reviews LIMIT 1")    }}()

为了使您的程序也等待这些goroutine,请使用

WaitGroup
已经生效的:

        // Pass something if needed        wg.Add(1)        go func() { defer wg.Done() db.Exec("SELECt * FROM reviews LIMIT 1")        }()


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/448216.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号