记录go数据库操作的bug——max_prepared_stmt_count,附分析过程

博客讲述了在Go中遇到的MySQL操作错误'Can’t create more than max_prepared_stmt_count statements',通过开启mysql的general_log,发现并发执行时,同一SQL会多次Prepare,导致max_prepared_stmt_count超出限制。源码分析指出Go SDK的一个潜在问题,即并发情况下可能导致过多的Prepare操作。解决方案是增大max_prepared_stmt_count参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Can’t create more than max_prepared_stmt_count statements (current value: 16382)
现网中出现这个错误,经过观察mysql的prepared_stmt_count参数并查看go源码,最后发现go数据库操作的sdk中有个bug。

  • 打开mysql的general_log开关
show variables where Variable_name like "general_log%";
set global general_log=on;

这个开关打开可以记录mysql执行过的所有的sql语句,便于观察。

  • 测试用例

func main() {
    var e error
    DB, e := sql.Open("mysql", "[use]:[passwd]@tcp(127.0.0.1:3306)/[db]")
    if e != nil {
        panic(e)
    }
    DB.SetMaxOpenConns(5)
    DB.SetMaxIdleConns(1)
    DB.Ping()


    stm, e := DB.Prepare("select * from test where id = ?")
    if e != nil {
        return
    }

    for i:=0; i<10000;i++ {
        go func() {
            result, err := stm.Exec(i)
            if err != nil {
            }
            fmt.Println(result)
        }()
    }

    <- time.After(time.Duration(5 * time.Second))
    fmt.Printf("++++++++++++++++++++==")
}
  • 打开mysql日志文件
show variables where Variable_name like "general_log%";

上述语句可以看到文件位置。

tail -f /var/lib/mysql/xxx.log | grep Pre

这里只查看Prepare命令的语句。

  • 执行上面的测试用例
    发现会执行最大连接数个Prepare。
2018-05-07T11:22:04.294438Z	 5529 Prepare	select * from test where id = ?
2018-05-07T11:22:04.335158Z	 5530 Prepare	select * from test where id = ?
2018-05-07T11:22:04.364443Z	 5531 Prepare	select * from test where id = ?
2018-05-07T11:22:04.364444Z	 5533 Prepare	select * from test where id = ?
2018-05-07T11:22:04.364489Z	 5532 Prepare	select * from test where id = ?
  • 问题分析
    经过上面的测试发现问题,如果并发量特别大的时候,同一个sql语句会多次执行Prepare,这样就存在一个问题,mysql中记录Prepared语句的参数Prepared_stmt_count会一直增大直到达到最大值max_prepared_stmt_count,最后就会报本文第一行的错误。

  • 源码分析
    这里贴几个比较重要的方法出来分析一下。


// Prepare creates a prepared statement for later queries or executions.
// Multiple queries or executions may be run concurrently from the
// returned stat
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值