2017-02-28 203 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函数返回的数据库可以同时使用并拥有自己的池