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 Pwm双极模式H桥驱动控制电机
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题