問題我編寫了一個將數據從 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 關注
- 155 瀏覽
添加回答
舉報
0/150
提交
取消