172 похожих чатов

Вечер добрый. Как бороться с race condition? В несколько потоков

клиентский код пытается заселектить, обновить или вставить данные. В таблице уникальный индекс на эти данные. При многопоточном доступе и select for update проскакивает вставка одних и тех же данных. Естественно падает по ограничению целостности. Можно как-то заблокироваться, но не на всей таблице?

8 ответов

4 просмотра

Может это нормально?

Viktor-AB Автор вопроса
Sergey Gr
Может это нормально?

Нужно заблокироваться на строке и не селектить, пока другая транзакция не отпустит.

Вариант 1. Использовать везде SERIALIZABLE (прочитав в документации, как именно), и получить надёжное решение проблемы. Вариант 2. Прочитать и осознать (попробовать на примерах) всю документацию про изоляцию в PostgreSQL (про serializable можно при этом не читать), понять механизмы, подумать о возможных взаимодействиях в конкретном случае, придумать и протестировать подход... и, если Вы хоть что-то сделаете неправильно, то проблема просто будет появляться значительно реже. ;) Для варианта 2 есть набор паттернов, которые часто помогают, а иногда — нет, если что.

Непонятно, в чем проблема? Вы делаете select for update, так? Это значит, что запрос заблокируется, если часть строк, которые вы выбираете, взяты другим select for update. Поэтому тут 2 варианта: 1) вы выбираете разные строки двумя транзакциями, в которых делается select for update, и изменяете их на одни и те же строки, поэтому получаете ошибку 2) либо просто делаете select for update и изменяете данные на те, которые уже вставлены. Выглядит так, что проблема либо в логике приложения, либо в том, что вы не хотите обрабатывать ошибки.

Viktor-AB Автор вопроса
Aleksey Stavrov
Непонятно, в чем проблема? Вы делаете select for u...

Не совсем. Для примера пытаюсь в несколько потоков в одной транзакции сделать select for update и если нет строки, то вставить. Ожидал, что будет работать блокировка, но по факту проскакивают попытки вставить одно и то же в разных транзакциях.

Viktor AB
Не совсем. Для примера пытаюсь в несколько потоков...

А unique constraint над суррогатным ключем или над чем-то существенным?

Viktor-AB Автор вопроса
Sergey Gr
А unique constraint над суррогатным ключем или над...

В синтетическом примере на все поля, кроме ключа.

Viktor AB
Не совсем. Для примера пытаюсь в несколько потоков...

Можете попробовать уровень изоляции serializable поставить, но его нужно будет включать вообще для всех транзакции. Тогда у вас эта ошибка скорей всего уйдёт и будет другая ошибка - ошибка сериализации данных. Более детально тут невозможно что-то подсказать, не поняв логику работы.

Похожие вопросы

Обсуждают сегодня

Какой-то там пердун в 90-х решил, что есть какая-то разная типизация. Кого вообще это волнует?
КТ315
49
void terminal_scroll() { memmove(terminal_buffer, terminal_buffer + VGA_WIDTH, buffer_size - VGA_WIDTH); memset(terminal_buffer + buffer_size - VGA_WIDTH, 0, VGA_WIDTH); ...
Егор
47
Всем привет! Подскажите, пожалуйста, в чем ошибка? Настраиваю подключение к MySQL. Либы лежат рядом с exe. Все как по "учебнику"
Евгений
16
А можете как-то проверить меня по знаниям по ассемблеру?
A A
132
Здравствуйте! У меня появилась возможность купить книгу "Изучай Haskell во имя добра!". Но я где-то слышал, что эта книга устарела. Насколько это правда??
E
22
Здравствуйте! Я вот на stepic решаю задачи на хаскеле https://stepik.org/lesson/8443/step/8?unit=1578 мой код import Data.List (isInfixOf) removing :: String -> [String] ->...
E
10
Камрады, кто тесно работал с vtv, хотел уточнить. Ширина column задаётся жёстко на этапе создания дерева или можно в рантайме ее менять программно (не мышкой)?
Ed Doc
10
да ладно ... что там неочевидного ? глянуть в исх-ки датасета и/или кверика чтобы понять в каком месте и как выполняется обращения к св-вам blablaSQL - минутное дело, даже е...
Сергей
7
Здесь для arm кто-нибудь кодит ?
Nothing
52
Всем привет, у меня есть сервер принимающий входящие HTTP подключения, как проверить, что подключение было через прокси или нет, есть какие то поля в заголовках по которым мо...
Кибер Бомж
8
Карта сайта