2016-04-20 2 views
1

Есть ли способ решить проблему, когда вы получаете параллельную вставку и обновление для одного и того же поля в многопоточной среде.Параллельные вставки и обновления postgres

Пример

Тема 1

BEGIN 
insert into users (name,age) values('spiderman',27) 
COMMIT 

резьбы 2

BEGIN 
update into users set age = 26 where name='spiderman'; 
COMMIT 

Большая часть обновления времени (транзакция) ничего не знает о вставке происходит, следовательно, оно проливает и ошибок.

То, что я вижу здесь, является классическим примером условий гонки, и одним из способов избежать условий гонки является использование блокировок.

Как применить блокировки (запись) к записи, которой еще нет в БД.

В приведенном выше примере для инструкции insert, чтобы Update знал, что запись еще не находится в БД.

+0

в веб-среде используйте https://en.wikipedia.org/wiki/Optimistic_concurrency_control (см. Аннотацию @Version в JPA) –

ответ

0

Решение на основе замков будет очень сложным и, вероятно, не стоит проблем. Вам нужно будет найти способ создания набора данных со всеми возможными полями «имя», а затем создать систему предупреждений об обнаружении данных. Скорее всего, он будет подвержен ошибкам.

Если, однако, проблема действительно гарантирует, что UPDATE не будет работать только после INSERT, есть более простые решения.

В частности, то, что приходит на ум, это что-то вроде:

BEGIN; 
    SELECT count(*) FROM users WHERE name = 'spiderman'; 
    -- on the application side, check to see what the result is 
    -- if it's 0, ROLLBACK 
    -- if it's >0: 
    UPDATE users SET age = 26 WHERE name = 'spiderman'; 
COMMIT; 

Если вы в конечном итоге откат, вы возвращаетесь и повторите попытку позже, означает ли это что-то простое, как sleep в течение 10 секунд и снова попробовать , или что-то более сложное, например, вернуть рабочий элемент в очередь и продолжить работу.

Если вы обеспокоены обновлениями между SELECT и UPDATE, вы можете SELECT FOR UPDATE, который заблокирует выбранные строки до завершения транзакции.

+0

Обычно у нас нет такой ситуации, поэтому введение сна затронет почти все вставки. Я не могу выбрать для обновления, поскольку параллельная операция, происходящая здесь, - это вставка и обновление. Выбор не является частью плана запроса. – Viren

+0

Я думал о блокировке как redis.setnx 'spiderman' – Viren

+0

Один из способов, о котором я могу думать, - установить уровень изоляции транзакций для diry uncommitted, что вы можете сказать об этом? – Viren

Смежные вопросы