doulu4316 2017-05-16 11:33
浏览 294
已采纳

MySQL连接错误(使用golang):连接过多,运行中的睡眠连接过多(超过8000个)show processlist

Execute insert, update, query and delete sequentially in for loop for 500,000 times, "too many connections" occurs after running for ten seconds even I set max connection of MySQL to 10,000. When running 'show processlist', the number of sleep status connections quickly raise up to around 10,000. (but it's fine when executing CURD separately, very quick to finish 1000,000 times of loop).

Only execute for loop for one time works fine: 2017-05-16 17:10:26 total cost time5.241008ms.

below is the code:

func insertUnis(db *sql.DB, name string){
    stmt_insert, err := db.Prepare("insert into memDB1 values(?,?,'world.cnworld.cnworld.cnworld.cn',?,'ee02:123::af01:9231:df18:8998:ee02:123::af01:9231:df18:8998:abcd','2017070035|2703258|1943|0|0|10.121.205.248|088:abcd:e02:123::/64','Framed-Interface-Id`varchar(64)COLLATEutf8_binNOTNULLdefaultthah','varchar(64)COLLATEutf8_binNOTNULLdefault0xBF019231DF18899934hdas','Call-From-Id`varchar(32)COLLATEd',?,'Current-Bandwidt','NAS-Port-Idvarchar(256)COLLATEutf8_binNOTNULLdefaultsrunk 6/0/36:33.351 0/0/0/0/0/0NAS-Port-Idvarchar(256)COLLATEutf8_binNOTNULLdefaultsrunk 6/0/36:33.351 0/0/0/0/0/0NAS-Port-Idvarchar(256)COLLATEutf8_binNOTNULLdefaultsrunk 6/0/36:33.351 0/0/0/0/0/0sefiuhu',48204,57239,2458787490,2458787490,2458787490,'Static-Bandwidthvhar(24)','Bas-Bandwidth` varchar(64) COLLATE utf8_bin NOT NULL defaultegse','Session-Id varchar(64) COLLATE utf8_bin NOT NULL defaultlasefjie','Coa-Session-Id` varchar(64) COLLATE utf8_bin NOT NULL defaultsdf','macaddr`varchar(32) COLLATE utf8',?,65535,45656,'Reseverd1` varchar(32) COLLATE u',4294967292)")
    if err != nil {
        Log(LL_ERROR, "stmt_insert Prepare err:", err.Error(), ".")
    }
    defer stmt_insert.Close()
    stmt_update, err := db.Prepare("update memDB1 set user_name=? where session_key=?")
    if err != nil {
        Log(LL_ERROR, "stmt_update Prepare err:", err.Error(), ".")
    }   
    defer stmt_update.Close()
    stmt_del, err := db.Prepare("delete from memDB1 where session_key=?")
        if err != nil {
            Log(LL_ERROR, "stmt_del Prepare err:", err.Error(), ".")
    }
    defer stmt_del.Close() 
    for i:=0;i<500000;i++{
        session_key:=string(Krand(64,3))
        user_name := string(Krand(64,3))
        frame_ip := string(Krand(32,3))     
        Nas_IP := string(Krand(32,3))   
        nat_ip := string(Krand(32,3))   

        _, err = stmt_insert.Exec(session_key,user_name,frame_ip,Nas_IP,nat_ip)
        if err != nil {
            Log(LL_ERROR, "stmt_insert Exec err:", err.Error(), ".")
        }

        _, err = stmt_update.Exec(string(Krand(64,3)), session_key)
        if err != nil {
            Log(LL_ERROR, "stmt_update Exec err:", err.Error(), ".")
        }
        sql := "SELECT * FROM memDB1 where session_key='" + session_key+"'"
        row, err := db.Query(sql)
        defer row.Close()
        if err != nil {
            Log(LL_ERROR, "Query err:", err.Error(), ".")
        }
        _, err = stmt_del.Exec(session_key)
         if err != nil {
            Log(LL_ERROR, "stmt_del Exec err:", err.Error(), ".")
        }
    }
    common_package.WgDay.Done()
    return
}

The MySQL process list:

mysql> show full processlist;
...............
| 1292138 | cid  | localhost:46799 | ciddb | Sleep   |    0 |          | NULL                  |
| 1292139 | cid  | localhost:46800 | ciddb | Sleep   |    0 |          | NULL                  |
| 1292140 | cid  | localhost:46801 | ciddb | Sleep   |    0 |          | NULL                  |
| 1292141 | cid  | localhost:46802 | ciddb | Sleep   |    0 |          | NULL                  |
+---------+------+-----------------+-------+---------+------+----------+-----------------------+
8719 rows in set (0.04 sec)

MySQL error messages:

2017-05-16 16:37:56 <LL_ERROR> stmt_insert Exec err:Error 1040: Too many connections. 
2017-05-16 16:37:56 <LL_ERROR> stmt_update Exec err:Error 1040: Too many connections. 
2017-05-16 16:37:56 <LL_ERROR> Query err:Error 1040: Too many connections. 2017-05-16 16:37:56 <LL_ERROR> stmt_del Exec err:Error 1040: Too many connections. 
2017-05-16 16:37:56 <LL_ERROR> stmt_insert Exec err:Error 1040: Too many connections. 
2017-05-16 16:37:56 <LL_ERROR> stmt_update Exec err:Error 1040: Too many connections 

MySQL setting: max_connections 10050 set global wait_timeout = 30; set global interactive_timeout = 30;

it's a memory table and had 5 indexes: KEY index1 (session_key), KEY index2 (Nas-IP), KEY index3 (user_name), KEY index4 (nat_ip), KEY index5 (frame_ip)

  • 写回答

1条回答 默认 最新

  • doue1925 2017-05-16 13:16
    关注

    You have a defer inside of a loop, which just pushes the row.Close function onto the stack, and will execute when the function returns. You probably want something like this instead:

    for i:=0;i<500000;i++{
        ...
        sql := "SELECT * FROM memDB1 where session_key='" + session_key+"'"
        row, err := db.Query(sql)
        if err != nil {
            Log(LL_ERROR, "Query err:", err.Error(), ".")
            continue
        }
        row.Close()
        ...
    }
    

    Supporting docs: https://blog.golang.org/defer-panic-and-recover

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 帮我写一个c++工程
  • ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
  • ¥15 关于smbclient 库的使用
  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教