2017-02-28 243 views
-7

我是Go(Golang)中的新成員。我寫了一個簡單的基準程序來測試MySQL的併發處理。當我增加併發通道數時,請繼續收到「撥號tcp 52.55.254.165:3306:getsockopt:連接被拒絕」,「意外的EOF」錯誤。golang MySQL「連接被拒絕」

每個例行程序都將1到n行的批量插入到一個簡單的客戶表中。該程序允許設置變量插入大小(在單個語句中的行數)和並行去程序的數量(每個去程序在上面執行一個插入)。程序工作正常,小數行< 100和數字去例程< 100.但是,當數字增加時,特別是並行去例程的數量,開始得到意外的EOF錯誤。

找到了線索。基於它們,我設置了數據庫最大連接和'max_allowed_pa​​cket'和'max_connections'。我還設置了去程序01​​,db.SetConnMaxLifetime(200),db.SetMaxIdleConns(10)。我嘗試過大數字和小數字(從10到2000)。似乎沒有什麼解決方案。

我打開了一個全局數據庫連接。下面的代碼片段:

// main package 

func main() { 

    var err error 
    db, err = sql.Open("mysql","usr:[email protected](ip:3306)/gopoc") 
    if err != nil { 
     log.Panic(err) 
    } 
    db.SetMaxOpenConns(1000) 
    db.SetConnMaxLifetime(1000) 
    db.SetMaxIdleConns(10) 

    // sql.DB should be long lived "defer" closes it once this function ends 
    defer db.Close() 

    if err = db.Ping(); err != nil { 
     log.Panic(err) 
    } 

    http.HandleFunc("/addCust/", HFHandleFunc(addCustHandler)) 

    http.ListenAndServe(":8080", nil) 
} 

// add customer handler 
func addCustHandler(w http.ResponseWriter, r *http.Request) { 

    // experected url: /addCust/?num=3$pcnt=1 
    num, _ := strconv.Atoi(r.URL.Query().Get("num")) 
    pcnt, _ := strconv.Atoi(r.URL.Query().Get("pcnt")) 

    ch := make([]chan string, pcnt) // initialize channel slice 
    for i := range ch { 
     ch[i] = make(chan string, 1) 
    } 

    var wg sync.WaitGroup 

    for i, chans := range ch { 
     wg.Add(1) 
     go func(cha chan string, ii int) { 
      defer wg.Done() 
      addCust(num) 
      cha <- "Channel[" + strconv.Itoa(ii) + "]\n" 
     }(chans, i) 
    } 

    wg.Wait() 

    var outputstring string 

    for i := 0; i < pcnt; i++ { 
     outputstring = outputstring + <-ch[i] 
    } 

    fmt.Fprintf(w, "Output:\n%s", outputstring) 
} 

func addCust(cnt int) sql.Result { 
... 
    sqlStr := "INSERT INTO CUST (idCUST, idFI, fName, state, country) VALUES " 

    for i := 0; i < cnt; i++ { 

     sqlStr += "(" + strconv.Itoa(FiIDpadding+r.Intn(CidMax)+1) + ", " + strconv.Itoa(FiID) +", 'fname', 'PA', 'USA), " 

    } 

    //trim the last , 
    sqlStr = sqlStr[0:len(sqlStr)-2] + " on duplicate key update lname='dup';" 

    res, err := db.Exec(sqlStr) 
    if err != nil { 
     panic("\nInsert Statement error\n" + err.Error()) 
    } 

    return res 
} 
+2

您必須顯示的代碼。 – Volker

+0

在下面添加代碼,謝謝... – Gary

回答

0

我想你是在你的每個例程中調用sql.open?

Open函數應該只調用一次。您應該在您的例程之間共享您打開的數據庫連接。由Open函數返回的數據庫可以同時使用並擁有自己的池