亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Golang 中對長時間運行的 MSSQL 事務的連接響應錯誤

Golang 中對長時間運行的 MSSQL 事務的連接響應錯誤

Go
呼喚遠方 2022-08-24 17:20:11
我有一個請求者,負責管理針對 Azure SQL 數據庫的 SQL 查詢。負責事務查詢的函數如下:import (    "context"    "database/sql"    "fmt"    "log"    "strings"    "time"    "github.com/cenkalti/backoff"    _ "github.com/denisenkom/go-mssqldb" // Need to import the SQL driver so we can tell Golang how to interpret our requests)// Helper function that does a single Exec with a transaction with a context on a query and variables.// This function will return an error if there are any failuresfunc (requester *Requester) doTransaction(ctx context.Context,     isolation sql.IsolationLevel, txFunc func(*sql.Tx) error) error {    // First, get the database connection; if this fails then return an error    conn, err := requester.getConn(ctx)    if err != nil {        return err    }    // Before we continue on, ensure that the connection is clsoed and returned to the connection pool    defer func() {        if err := conn.Close(); err != nil {            log.Printf("Close failed, error: %v", err)        }    }()    // Next, start the transaction with the given context and the default isolation    tx, err := requester.getTx(ctx, conn, isolation)    if err != nil {        return err    }總的來說,這很有效。我注意到的一個問題是,當各個請求之間經過很長時間時,我會在第一次重試時遇到錯誤,然后在后續重試時出錯,最終導致失敗。我的想法是,問題與此錯誤有關。從本質上講,微軟似乎在30分鐘后使空閑請求無效。但是,由于我將最大空閑時間設置為10分鐘,因此這應該不是問題所在。i/o timeoutbad connection這是怎么回事,我該如何解決這個問題?
查看完整描述

1 回答

?
子衿沉夜

TA貢獻1828條經驗 獲得超3個贊

經過一些調查,我發現數據庫連接在 30 分鐘窗口后變得陳舊,修改連接池的生存期或空閑時間并不能真正解決此問題。因此,為了緩解這個問題,我所做的是事先修改我的函數以ping服務器,這樣我就可以確保連接是“新鮮的”,因為缺乏更好的術語。getConn


func (requester *Requester) getConn(ctx context.Context) (*sql.Conn, error) {


    // First, attempt to ping the server to ensure that the connection is good

    // If this fails, then return an error

    if err := requester.conn.PingContext(ctx); err != nil {

        return nil, err

    }


    // Create an object that will dictate how and when the retries are done

    // We currently want an exponential backoff that retries a maximum of 5 times

    repeater := backoff.WithContext(backoff.WithMaxRetries(

        backoff.NewExponentialBackOff(), 5), ctx)


    // Do a retry operation with a 500ms wait time and a maximum of 5 retries

    // and return the result of the operation therein

    var conn *sql.Conn

    if err := backoff.Retry(func() error {


        // Attempt to get the connection to the database

        var err error

        if conn, err = requester.conn.Conn(ctx); err != nil {


            // We failed to get the connection; if we have a login error, an EOF or handshake

            // failure then we'll attempt the connection again later so just return it and let

            // the backoff code handle it

            log.Printf("Conn failed, error: %v", err)

            if isLoginError(err, requester.serverName, requester.databaseName) {

                return err

            } else if strings.Contains(err.Error(), "EOF") {

                return err

            } else if strings.Contains(err.Error(), "TLS Handshake failed") {

                return err

            }


            // Otherwise, we can't recover from the error so return it

            return backoff.Permanent(err)

        }


        return nil

    }, repeater); err != nil {

        return nil, err

    }


    return conn, nil

}


查看完整回答
反對 回復 2022-08-24
  • 1 回答
  • 0 關注
  • 131 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號