【问题标题】:Go/Golang sql.DB reuse in functionsGo/Golang sql.DB 在函数中重用
【发布时间】:2013-11-27 11:31:42
【问题描述】:

sql.Open() 返回 *sql.DB 类型的变量

我有一个函数可以调用其他 10 个函数,这些函数都需要进行数据库调用

这样做是否更正确/更有效:

  • 将 *sql.DB 指针发送到每个函数,或者
  • 在每个函数中创建一个新的 *sql.DB 对象

意义

func DoLotsOfThings() {
    db, _ := sql.Open()
    defer db.Close()
    DoTask1(db)
    DoTask2(db)
}

func DoLotsOfThings() {
    DoTask1()
    DoTask2()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

func DoTask1() {
    db, _ := sql.Open()
    defer db.Close()
}

我问的原因是因为我目前正在向每个函数发送指针,而我的驱动程序似乎坏了。我正在使用 http://code.google.com/p/odbc ,这让我相信每个功能都应该有自己的功能,并且我可以依赖驱动程序的内部结构。

编辑

RE 驱动损坏,仅在高流量环境下发生。它只发生在十分钟左右的时间之后。这使我相信存在某种内存泄漏导致使用驱动程序停止工作。但是我为 *sql.DB 的每个实例推迟了 db.Close(),所以我不知道我还能做些什么来解决这个问题。

andybalholm 说连接池是在内部处理的,这似乎是准确的,因为它仅在我尝试执行某些操作后才中断,而不是在我调用 sql.Open() 时中断

如果我让我的 Go 应用程序运行,它将无法执行任何类型的 SQL 查询,但如果我尝试单独运行其他 Go 测试连接到 MSSQL 并运行查询,它就可以工作。

【问题讨论】:

标签: go odbc freetds unixodbc


【解决方案1】:

您不需要到处打开数据库连接。 database/sql 包在内部进行连接池,根据需要打开和关闭连接,同时提供可以并发使用的单个连接的假象。

您可能需要在其他地方寻找驱动程序损坏的原因。一些更多的细节会让人们更容易弄清楚发生了什么。

【讨论】:

  • 所以我应该引用 sql.Open 和生成的 *sql.DB。看来您对池的看法是正确的,只有在尝试执行查询时才会出错。奇怪的是,我的 go 应用程序无法连接到 MSSQL,但在它之外,只要我不运行存储过程,我就可以运行能够连接的测试。这一切都很奇怪。
  • 在尝试调试数据库/sql 应用程序时要记住的一点是,由于连接池,执行 sql.Open 时通常不会出现连接错误;他们等到您在连接上运行第一个查询。
【解决方案2】:

全局声明var db *sql.DB,然后在您的代码中重用它。这是一个示例(简化):

var db *sql.DB

func DoLotsOfThings() {
    DoTask1(db)
    DoTask2(db)
}

func main() {
  db, _ = sql.Open() # or whatever you use
  defer db.Close()
  DoLotsOfThings()
}

在全局范围内声明*sql.DB 还具有一些额外的好处,例如SetMaxIdleConns(调节连接池大小)或preparing 应用程序中的SQL 语句。

【讨论】:

  • 感谢您的留言!
猜你喜欢
  • 2021-12-24
  • 1970-01-01
  • 2014-12-16
  • 2019-10-28
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 2017-10-06
  • 1970-01-01
相关资源
最近更新 更多