Объемные транзакции в транзакции 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.