2016-03-05 94 views
1

我正在使用此驱动程序:https://github.com/denisenkom/go-mssqldb以及使用Azure SQL数据库标准S3级别进行生产时,我们得到的方式太多了ErrBadconn - driver: Bad connection返回。如何使用Azure SQL数据库来防止/处理ErrBadConn

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

典型的数据库函数调用

包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() 
} 

在网页API,以便在短

func main() { 
    db := dal.Database{} 
    db.Open() 
    defer db.Close() 

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 
    entities := &dal.Entites{} 
    id, err := entities.Add(dal.Entity{Field1: "a", Field2: "b"}) 
    if err != nil { 
     // here all across my web api and other web package or cli cmd that uses the dal I'm getting random ErrBadConn 
    } 
    }) 
} 

,所述dal包跨越多个天青网络应用和命令行共享去应用程序。

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

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

我已经三重检查访问数据库的包上的所有地方,确保所有sql.Rows已关闭,所有db.Prepare语句都已关闭。作为和这里的例子是一个典型的查询功能的样子:

func (e *Entities) GetByID(id int64) ([]Entity, error) { 
    rows, err := db.Query("SELECT * FROM Entities WHERE ID = ?", id) 
    if err != nil { 
     return nil, err 
    } 
    defer rows.Close() 

    var results []Entity 
    for rows.Next() { 
     var r Entity 
     err := readEntity(rows, &r) 
     if err != nil { 
      return nil, err 
     } 
     results = append(results, r) 
    } 

    if err = rows.Err(); err != nil { 
     return nil, err 
    } 

    return results, nil 
} 

readEntity基本上只做上的字段Scan

我不认为它是代码相关的,单元测试在本地运行良好。它只是在有时运行驱动程序后才部署到Azure:连接不良开始频繁出现。

我跑这个查询尝试,看看在这个问题建议:Azure SQL server max pool size was reached error

select * from sys.dm_exeC_requests

但我不完全相信,我应该在这里关注。

我已经做了/确定的事情。

  1. 由于它的建议,该database/sql应该处理连接池,所以有数据库连接的全局变量应该罚款。

  2. 确保sql.Rowsdb.Prepare声明处处关闭。

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

  4. 有一个为我使用的SQL驱动程序的问题,谈到SQL Azure中进行数据库连接,如果他们空转多吴丹2分钟糟糕的状态。 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 
} 

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

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

+0

是你的应用程序和SQL Azure的数据库在同一地区举行? – Daredevil

+0

@Abhimanyu是的,他们都在同一地区北部中央美国 –

+0

这是正确的。重试逻辑用于这些场景。那么将代码复制到GO将会很好:https://azure.microsoft.com/en-us/documentation/articles/sql-database-develop-csharp-retry-windows/ –

回答

0

我没有看到任何关闭数据库的地方。最佳实践(使用其他语言 - 对Go没有正面评价)是在使用后关闭/取消分配/取消引用数据库对象,将连接释放回池中。如果你的连接资源耗尽,你会被告知你需要释放东西。将参考文献保持为打开状态意味着没有其他人可以使用该连接,因此它会一直保留,直到它被回收为止,因为它已超时。这就是为什么你会间歇性地获取它,而不是始终如一 - 这取决于在特定时间段内发生一定数量的连接。

+0

不,包数据库/ sql正在处理该池并处理连接的创建和回收 –

相关问题