如何使用 Azure SQL 数据库防止/处理 ErrBadConn

我正在使用这个驱动程序:https : //github.com/denisenkom/go-mssqldb并且在使用 Azure SQL 数据库标准 S3 级别的生产中,我们得到了太多 ErrBadconn -driver: Bad connection返回。


我怎样才能防止或至少优雅地处理它。这里有一些代码来展示事情是如何设置的。


一个典型的数据库函数调用


包 dal


var db *sql.DB


type Database struct{}


func (d Database) Open() {

    newDB, err := sql.Open("mssql", os.Getenv("dbconnestion"))

    if err != nil {

        panic(err)

    }


    err = newDB.Ping()

    if err != nil {

        panic(err)

    }


    db = newDB

}


func (d Database) Close() {

    db.Close()

}

// ... in another file

func (e *Entities) Add(entity Entity) (int64, error) {

    stmt, err := db.Prepare("INSERT INTO Entities VALUES(?, ?)")

    if err != nil {

        return -1, err

    }

    defer stmt.Close()


    result, err := stmt.Exec(entity.Field1, entity.Field2)


    if err != nil {

        return -1, err

    }


    return result.LastInsertId()

}

简而言之,该dal包在多个 Azure Web 应用程序和命令行 Go 应用程序之间共享。


我看不到一种模式,即那些频繁且随机发生的错误。我们正在使用 Bugsnag 来记录我们所有应用程序的错误。


为了完成,有时会达到我们的标准 S3 限制 200 个并发连接。

我在访问数据库的包上的所有地方都进行了三重检查,确保所有内容sql.Rows都已关闭,所有db.Prepare语句都已关闭。作为示例,典型的查询函数如下所示:

readEntity基本上只做Scan上的字段。

我认为这与代码无关,单元测试在本地运行良好。有时在运行后仅部署到 Azure 一次,驱动程序:错误连接开始非常频繁地出现。

我已运行此查询以尝试查看此问题中的建议:Azure SQL server max pool size was connected 错误

select * from sys.dm_exeC_requests

但我不确定在这里我应该注意什么。

我做过/确定过的事情。

  1. 正如建议的那样,database/sql应该处理连接池,因此为数据库连接设置一个全局变量应该没问题。

  2. 确保sql.Rowsdb.Prepare声明在任何地方都是关闭的。

  3. 将 Azure SQL 级别提高到 S3。

  4. 我正在使用的 sql 驱动程序存在问题,如果它们空闲超过 2 分钟,则 Azure SQL 使数据库连接处于错误状态。 https://github.com/denisenkom/go-mssqldb/issues/81

database/sql处理连接池的方式是否与 Azure SQL 数据库的管理方式不兼容。

有没有办法优雅地处理这个问题?我知道 C#/Entity Framework 有一个针对 Azure SQL 的连接弹性/重试逻辑,是不是出于类似的原因?我如何实现这一点而不必在我的错误处理中到处传递?我的意思是我不想清楚地做这样的事情:

if err == sql.ErrBadConn {

  // close and re-open the global db object

  // retry

}

这当然不是我唯一的选择吗?


任何帮助将非常受欢迎。谢谢


富国沪深
浏览 121回答 2
2回答

萧十郎

岩,您多久遇到这些连接问题?我建议您构建重试逻辑,以便从错误的连接中优雅地失败。以下是使用 C# 的方法:https : //azure.microsoft.com/en-us/documentation/articles/sql-database-develop-csharp-retry-windows/如果您仍然觉得需要帮助,请随时通过 meetb@microsoft.com 向我发送包含您的服务器名称和数据库名称的电子邮件,我们将让我们的团队调查此问题。干杯,见面

沧海一幻觉

我没有看到您关闭数据库的任何地方。最佳实践(在其他语言中 - 对 Go 不利)是在使用后关闭/解除分配/取消引用数据库对象,将连接释放回池中。如果你的连接资源用完了,你会被告知你需要释放一些东西。保持引用打开意味着没有其他人可以使用该连接,因此它会一直存在,直到它因为超时而被回收。这就是为什么您会间歇性地而不是始终如一地获得它 - 这取决于在特定时间段内发生一定数量的连接。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go