Если вы хотите использовать базовые функции c ORM, вы можете использовать FOR UPDATE
в качестве опции запроса при извлечении записи, база данных заблокирует запись для этого указанного c соединения до это соединение выдает запрос UPDATE
для изменения этой записи.
Оба оператора SELECT
и UPDATE
должны произойти в одном соединении, что означает, что вам нужно обернуть их в транзакция (в противном случае Go может отправить второй запрос по другому соединению).
Обратите внимание, что этот сделает каждое другое соединение, которое хочет SELECT
той же записи, подождет , пока вы сделали UPDATE
. Это не проблема для большинства приложений, но если у вас либо очень высокий параллелизм, либо время между SELECT ... FOR UPDATE
и UPDATE
после этого, это может быть не для вас.
В дополнение к FOR UPDATE
, опция FOR SHARE
звучит так, как будто она также может работать для вас, с меньшим количеством блокировок (но я не знаю этого достаточно хорошо, чтобы сказать это наверняка).
Примечание: Это предполагает, что вы используете СУБД, которая поддерживает SELECT ... FOR UPDATE
; если это не так, обновите вопрос, чтобы сообщить нам, какую СУБД вы используете.
Другой вариант - просто go вокруг ORM и сделать db.Exec("UPDATE counter_table SET counter = counter + 1 WHERE id = ?", 42)
(хотя см. { ссылка } для некоторых ловушек).