Объемные транзакции в транзакции sql в golang
Я возился с пакетом golang sql с транзакциями, и я пытаюсь понять, как делать массовые upserts без обмена сообщениями "за каждую вставку" для каждой строки. Примеры здесь не показывают, как будут выполняться любые массовые запросы.
updateMoney, err := db.Prepare("INSERT INTO balance set money=?, id=? ON DUPLICATE UPDATE balance SET money=money+? WHERE id=?")
...
tx, err := db.Begin()
...
res, err := tx.Stmt(updateMoney).Exec(123.45, 1, 123.45, 1)
res, err := tx.Stmt(updateMoney).Exec(67.89, 2, 67.89, 2)
res, err := tx.Stmt(updateMoney).Exec(10.23, 3, 10.23, 3)
...
tx.Commit()
В идеале я мог бы взять подготовленный запрос и создать список upserts, который будет отправлен одновременно... но здесь мы получаем результат из базы данных после каждого выполнения. Любые предложения о том, как это сделать?
Изменить:
Мой коллега нашел этот открытый билет, который описывает проблему... это выглядит более серьезной проблемой, чем строго в контексте транзакции.
Ответы
Ответ 1
В зависимости от того, какой драйвер вы используете, некоторые драйверы/базы данных вообще не поддерживают транзакции.
Например go-sql-driver/mysql поддерживает транзакции просто отлично.
Ваш код должен работать, или вы можете немного изменить его:
tx, err := db.Begin()
...
stmt, err := tx.Prepare(`INSERT INTO balance set money=?, id=? ON DUPLICATE UPDATE balance SET money=money+? WHERE id=?`)
res, err := stmt.Exec(123.45, 1, 123.45, 1)
res, err := stmt.Exec(67.89, 2, 67.89, 2)
res, err := stmt.Exec(10.23, 3, 10.23, 3)
...
tx.Commit()
Также проверьте этот ответ, который содержит множество подробностей о транзакциях.
Ответ 2
Таким образом, хотя мы не могли делать отдельные запросы для каждого upsert, мы действительно писали допустимый mysql для массовых upserts в одном выражении...
INSERT INTO balance (id, money) VALUES (1, 123.45), (2, 67.89), (3, 10.23)
ON DUPLICATE KEY UPDATE money = money + values(money)
Таким образом, для тех, кто хочет выполнить массовое обновление, существует шаблон для работы с любыми ограничениями драйвера mysql.