у нас есть некоторые постоянные данные в приложении, которые запрашиваются с сервера и затем сохраняются в базе данных, чтобы мы могли отслеживать дополнительную информацию. Поскольку мы не хотим запрашивать, когда объект используется в памяти, мы делаем select for update
, чтобы другие потоки, которые хотят получить те же данные, были заблокированы.
Я не уверен, как select for update
обрабатывает несуществующие строки. Если строка не существует и другой поток попытается выполнить еще один select for update
в той же строке, будет ли этот поток заблокирован до завершения другой транзакции или он также получит пустой набор результатов? Если он получает только пустой набор результатов, есть ли способ также заблокировать его, например, сразу вставив пропущенную строку?
EDIT:
Поскольку было замечание, что мы могли бы заблокировать слишком много, вот еще некоторые подробности о конкретном использовании в нашем случае. В сокращенном псевдокоде наш программный поток выглядит так:
d = queue.fetch();
r = SELECT * FROM table WHERE key = d.key() FOR UPDATE;
if r.empty() then
r = get_data_from_somewhere_else();
new_r = process_stuff( r );
if Data was present then
update row to new_r
else
insert new_r
Этот код запускается в нескольких потоках, и данные, извлекаемые из очереди, могут относиться к одной и той же строке в базе данных (следовательно, к блокировке). Однако, если несколько потоков используют данные, которым нужна одна и та же строка, эти потоки должны быть секвенированы (порядок не имеет значения). Однако эта последовательность не работает, если строка отсутствует, потому что мы не получаем блокировку.
EDIT:
Пока у меня есть следующее решение, которое мне кажется уродливым.
select the data for update
if zero rows match then
insert some dummy data // this will block if multiple transactions try to insert
if insertion failed then
// somebody beat us at the race
select the data for update
do processing
if data was changed then
update the old or dummy data
else
rollback the whole transaction
Однако я не уверен на 100%, что это действительно решает проблему, и при этом это решение не кажется хорошим стилем. Так что если кто-то может предложить что-то более полезное, это было бы здорово.