FOR UPDATE для условия WHERE id IN ( $1, $2 ) — нет никакой гарантии, что записи будут блокироваться в последовательности аргументов в запросе. как база наткнётся, так и возьмёт лок. и просто наличие условия SELECT FOR UPDATE WHERE id IN ( $1, $2 ) — практически гарантия для дедлоков.
* зачем явные блокировки нужны? нельзя сделать просто UPDATE?
1) а как лучше давать логи из консоли? 2) а можно как-то дополнительным / другим локом SELECT, чтобы он прошел по таблице и либо залочил одновременно два, либо повис в ожидании, пока другие не разлочат? кажется, также можно решить эту проблему активным ожиданием через суффикс NO WAIT и цикл, но не хочется активное ожидание в коде 3) просто UPDATE, кажется, не сработает же? когда транзакция делает UPDATE в двух аккаунтах, нужно, чтобы остальные, кто пытается работать с хотя бы одним из двух, повис как раз где-нибудь в SELECT FOR UPDATE и уже после получение доступа читал актуальные закомиченные данные P.S. если что, я только-только разбираюсь с транзакциями в sql по-хорошему, поэтому вот так P.P.S. документацию постгры, постгреспро, главу в книжке читал. не помогло до конца понять этот момент.
1) копировать текстом, прикладывать текстом 2) UPADTE берёт такой же лок, что и SELECT FOR UPDATE. проблема не в локе, а в последовательности блокирования записей 3) сработает. но шанс получить дедлок сохраняется. 4) вы не ответили — вам точно надо блокировать сразу 2 id? можно же сделать транзакцию и в ней UPDATE меньшего из 2-х ID, затем большего из двух. 5) нет такой базы постгры, не коверкайте
5) простите колхозника 😉
кажется, вы правы, если задать порядок, сначала меньший id, потом больший, и провести так 2 update один за другим - этого достаточно.
Обсуждают сегодня