我是新手(Golang)。我编写了一个简单的基准程序,以测试MySQL并发处理。继续获取" DIAL TCP 52.55.254.165:3306:GetSockopt:拒绝连接","出乎意料的EOF"错误时,当我增加并发通道的数量时。
每个GO例程都在简单的客户表上进行1至n行数的批次插入。该程序允许设置可变插入大小(单个语句中的行数)和并行GO例程的数量(每个GO例程都在上面执行一个插入)。程序可正常工作,小数行< 100 and Number Go例程< 100。但是,当数字增加时,开始遇到意外的EOF错误,尤其是并行GO例程的数量。
确实搜索了线索。基于它们,我设置了数据库最大连接和" max_allowed_packet"one_answers" max_connections"。我还设置了GO程序db.db.SetMaxOpenConns(200)
,db.SetConnMaxLifetime(200)
,db.SetMaxIdleConns(10)
。我已经尝试了大数字和小(从10到2000年)。似乎没有解决程序。
我有一个全局数据库连接打开。下面的代码段:
// main package
func main() {
var err error
db, err = sql.Open("mysql","usr:pwd@tcp(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 errorn" + err.Error())
}
return res
}
我想您在每个例程中都在调用sql.open?
应仅调用一次打开功能。您应该在例程之间共享打开的数据库连接。开放函数返回的数据库可以同时使用,并具有自己的池