При выполнении параллельного MERGE
, в то время как каждый сеанс использует другое значение (показано ниже в сноске ниже) для столбца первичного ключа id
, все нормально, если я делаю это вручную в двух сеансах терминала.
MERGE
INTO x
USING (SELECT *** as id FROM DUAL) MERGE_SRC
ON (x.id = MERGE_SRC.id)
WHEN MATCHED THEN UPDATE SET val = val + 1 WHERE id = ***
WHEN NOT MATCHED THEN INSERT VALUES (***, 99);
COMMIT;
Однако при запуске многопоточного теста нагрузки с тремя или более потоками я буду относительно быстро работать в ORA-08177 with locked table
. Почему это? (И почему он не детерминирован в том смысле, что это не всегда происходит, когда транзакции перекрываются?)
Таблица была создана с помощью
create table x (id int primary key, val int);
SQL Server btw никогда не выдает исключения с эквивалентным оператором MERGE, выполняющим тот же эксперимент. Это даже верно при одновременной работе с одной строкой.
Это потому, что, возможно, MERGE не является атомарным, а сериализуемый режим работает оптимистично, так что гонка может отображаться только с достаточным количеством споров? Тем не менее, почему это происходит , даже если одновременно не работает одна и та же строка?
Btw, мои попытки исправить это, используя самый строгий доступный замок, не увенчались успехом. Поэтому любые идеи о том, как сделать этот атом, очень ценятся. Похоже, что ослабление уровня изоляции избавит меня от исключения, но риск несоответствий в случае, если в одной строке окажется 2 обновления (в противном случае, почему бы это не произошло в сериализованном режиме в первую очередь).