问题我编写了一个将数据从 BigQuery 同步到 MySQL 数据库的应用程序。我尝试每 3 小时分批插入大约 10-20k 行(每批最多 10 项)。出于某种原因,当它尝试将这些行更新插入 MySQL 时,我收到以下错误:不能创建超过 max_prepared_stmt_count 个语句:错误 1461:不能创建超过 max_prepared_stmt_count 个语句(当前值:2000)我的“相关代码”// ProcessProjectSkuCost receives the given sku cost entries and sends them in batches to upsertProjectSkuCosts()func ProcessProjectSkuCost(done <-chan bigquery.SkuCost) { var skuCosts []bigquery.SkuCost var rowsAffected int64 for skuCostRow := range done { skuCosts = append(skuCosts, skuCostRow) if len(skuCosts) == 10 { rowsAffected += upsertProjectSkuCosts(skuCosts) skuCosts = []bigquery.SkuCost{} } } if len(skuCosts) > 0 { rowsAffected += upsertProjectSkuCosts(skuCosts) } log.Infof("Completed upserting project sku costs. Affected rows: '%d'", rowsAffected)}// upsertProjectSkuCosts inserts or updates ProjectSkuCosts into SQL in batchesfunc upsertProjectSkuCosts(skuCosts []bigquery.SkuCost) int64 { // properties are table fields tableFields := []string{"project_name", "sku_id", "sku_description", "usage_start_time", "usage_end_time", "cost", "currency", "usage_amount", "usage_unit", "usage_amount_in_pricing_units", "usage_pricing_unit", "invoice_month"} tableFieldString := fmt.Sprintf("(%s)", strings.Join(tableFields, ","))我的问题:为什么我max_prepared_stmt_count在立即执行准备好的语句时点击了(请参阅函数upsertProjectSkuCosts)?我只能想象这是某种并发性,它在准备和执行所有这些语句之间同时创建大量准备好的语句。另一方面,我不明白为什么会有这么多并发,因为通道中的通道ProcessProjectSkuCost是一个大小为 20 的缓冲通道。
1 回答
泛舟湖上清波郎朗
TA贡献1818条经验 获得超3个赞
您需要关闭里面的声明upsertProjectSkuCosts()
(或重新使用它 - 请参阅本文末尾)。
当您调用 时db.Prepare()
,会从内部连接池中获取一个连接(如果没有任何空闲连接,则会创建一个新连接)。stmt.Exec()
然后在该连接上准备该语句(如果调用时该连接不可用,则该语句也会在另一个连接上准备)。因此,这会在您的数据库中为该连接创建一个语句。这个语句不会神奇地消失——在一个连接中有多个准备好的语句是完全有效的。Golang可以看到stmt
超出范围,看到它需要某种清理然后进行清理,但 Golang 不会(就像它不会为您关闭文件和类似的东西一样)。所以你需要自己使用stmt.Close()
. 你打电话时stmt.Close()
,驱动程序将向数据库服务器发送命令,告诉它不再需要该语句。
defer stmt.Close()
最简单的方法是在检查后添加err
以下内容db.Prepare()
。
您还可以做的是,准备一次语句并使其可用于upsertProjectSkuCosts
(通过将stmt
into传递upsertProjectSkuCosts
或通过构造upsertProjectSkuCosts
结构的 func,以便结构可以具有 的属性stmt
)。如果你这样做,你不应该调用stmt.Close()
- 因为你不再创建新的语句,你正在重新使用现有的语句。
- 1 回答
- 0 关注
- 120 浏览
添加回答
举报
0/150
提交
取消