2012-03-04 5 views
7

В операторе обновления Oracle SQL, предполагая, что обновление повлияет на 5 строк, выполняет ли инструкция обновления каждые 5 строк одновременно или последовательно? Например.В инструкции Oracle SQL update обновляется ли обновление строки одновременно?

UPDATE table1 
set column2 = 'completed' WHERE 
index between 1 AND 5 

В приведенном выше заявлении, будет индекс 1 до 5 обновляется в последовательности, т.е. 1, 2, 3, 4, затем 5, или же оно будет происходить одновременно (1-5 все сразу).

Я ссылался на Oracle documentation, но кажется, что об этом ничего не говорится.

+0

Логически, они происходят одновременно. На практике они этого не делают, но вы не сможете определить разницу. Это становится более интересным, если вы делаете 'UPDATE Table1 SET Index = Index + 1 WHERE Index BETWEEN 1 AND 5'. –

ответ

4

После выполнения инструкции UPDATE эффекты инструкции станут видимыми для остальной части транзакции (и если вы передадите ее другим транзакциям). В каком порядке Oracle физически это сделает, это деталь реализации (аналогично, как порядок результата SELECT не гарантируется , если только не указывается ORDER BY).


В большинстве случаев этот заказ не имеет значения для клиента. В одном случае, когда это возможно, следует избегать взаимоблокировок с другой транзакцией, которая обновляет перекрывающийся набор строк. UPDATE блокирует обновляемую строку до конца транзакции, поэтому, если две транзакции попытаются заблокировать одни и те же строки, но в другом порядке может возникнуть взаимоблокировка.

Стандартный способ избежать взаимоблокировок - всегда фиксировать в определенном порядке. К сожалению, UPDATE не имеет предложения ORDER BY, но вы можете сделать это:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
SELECT ... WHERE condition ORDER BY ... FOR UPDATE; 
UPDATE ... WHERE condition; 
COMMIT; 

Где condition одинакова для обоих заявлений. Сериализуемый уровень изоляции необходим для WHERE, чтобы всегда видеть один и тот же набор строк в обоих операторах.

Или в PL/SQL вы могли бы сделать что-то вроде этого:

DECLARE 
    CURSOR CUR IS SELECT * FROM YOUR_TABLE WHERE condition ORDER BY ... FOR UPDATE; 
BEGIN 
    FOR LOCKED_ROW IN CUR LOOP 
     UPDATE YOUR_TABLE SET ... WHERE CURRENT OF CUR; 
    END LOOP; 
END; 
/
2

Ссылка, которую вы предоставили, действительно покрывает это. Oracle всегда обеспечивает согласованность чтения на уровне инструкций - это означает, что ни один запрос в таблице1 не вернет некоторые обновленные записи, а некоторые нет. Это будет все или ничего и независимо от уровня изоляции.

+0

Спасибо. Для дальнейшего уточнения, если индекс 4 имеет блокировку чтения, будет ли инструкция обновления ждать блокировки чтения, чтобы обновить все 5 строк? – Ted

+0

@Ted: В Oracle читатели и писатели не блокируют друг друга. Когда данные обновляются, старые данные автоматически сохраняются на некоторое время (UNDO). Это позволяет запросам считывать данные в определенный момент времени независимо от любых изменений. –

+0

@jonearles Да, но авторы ** делают ** блокируют друг друга (когда они пишут в те же строки). Писатели будут блокировать строку за строкой, что означает, что существует вероятность блокировки, если записи не выполняются в одном порядке всеми транзакциями. Поскольку UPDATE не имеет предложения ORDER BY, для гарантирования порядка блокировки должен использоваться отдельный 'SELECT ... ORDER BY ... FOR UPDATE'. –

4

Потенциально также.

В этом случае, поскольку вы просто обновляете 5 строк, было бы невероятно маловероятным, чтобы параллельный DML был уместным. Предполагая, что UPDATE не вызывает параллельный DML, строки будут обновляться последовательно, хотя порядок обновления строк произволен. INDEX 1 может быть первым, кто будет обновлен, последний будет обновлен, или он может быть обновлен посередине. Это зависит от плана запроса.

2

UPDATE, DELETE и INSERT не имеют определенного порядка. Концептуально они применяются к набору и выполняются все сразу. Практически говоря, не полагайтесь на какую-либо последовательность, которую вы можете наблюдать - это деталь реализации, которая может меняться и происходит только потому, что реальный мир мешает теории.

+0

Спасибо! Я полагаю, что обновление выполняется на основе набора, т. Е. Обновление будет ждать, пока все строки будут доступны до выполнения инструкции обновления? – Ted

+0

@Ted: Oracle блокирует блокировку уровня, но все строки не нужно разблокировать при запуске обновления. – jmoreno

0

Все записи будут обновлены как одна запись за одну транзакцию. Oracle не гарантирует порядок в последовательности обновления.

Вы можете обновить любое поле по значению dbms_transaction.local_transaction_id в своей таблице, чтобы проверить его.

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