2012-03-04 42 views
7

Trong câu lệnh cập nhật Oracle SQL, giả sử bản cập nhật sẽ ảnh hưởng đến 5 hàng, bản cập nhật có cập nhật tất cả 5 hàng đồng thời hoặc tuần tự không? Ví dụ.Trong câu lệnh cập nhật Oracle SQL, cập nhật hàng có xảy ra đồng thời không?

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

Trong tuyên bố trên, sẽ chỉ số 1-5 được cập nhật theo thứ tự, ví dụ: 1, 2, 3, 4 rồi 5, hoặc nó có thể xảy ra đồng thời (1-5 tất cả cùng một lúc).

Tôi đã gọi đến Oracle documentation nhưng có vẻ như không có gì được đề cập về điều này.

+0

Một cách logic, chúng xảy ra đồng thời. Trong thực tế, họ không, nhưng bạn sẽ không thể phát hiện sự khác biệt. Sẽ thú vị hơn nếu bạn làm 'UPDATE Table1 SET Index = Index + 1 WHERE Index GIỮA 1 VÀ 5'. –

Trả lời

4

Sau khi câu lệnh UPDATE đã được thực hiện, hiệu ứng của câu lệnh sẽ hiển thị cho phần còn lại của giao dịch (và nếu bạn cam kết, với các giao dịch khác). Theo thứ tự Oracle sẽ làm gì, là chi tiết thực hiện (tương tự như cách mà thứ tự kết quả SELECT không được bảo đảm trừ khi bạn chỉ định ORDER BY).


Trong hầu hết các trường hợp, thứ tự này không quan trọng với khách hàng. Một trường hợp mà nó có thể là để tránh deadlocks với một giao dịch đang cập nhật tập hợp các hàng chồng chéo. UPDATE sẽ khóa hàng đang được cập nhật cho đến khi kết thúc giao dịch, vì vậy nếu hai giao dịch cố gắng khóa các hàng tương tự, nhưng theo thứ tự khác nhau, một bế tắc có thể xảy ra.

Cách tiêu chuẩn để tránh deadlocks là luôn luôn khóa theo thứ tự được xác định rõ ràng. Rất tiếc, UPDATE không có mệnh đề ORDER BY, nhưng bạn có thể thực hiện điều này:

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

Trường hợp condition tương tự cho cả hai câu lệnh. Mức cô lập tuần tự là cần thiết cho WHERE để luôn thấy cùng một tập hợp các hàng trong cả hai câu lệnh.

Hoặc, trong PL/SQL bạn có thể làm một cái gì đó như thế này:

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

Liên kết bạn đã cung cấp thực sự thực hiện việc này. Oracle luôn luôn thi hành mức độ nhất quán đọc báo cáo - điều này có nghĩa là không có truy vấn nào trên bảng 1 sẽ trả về một số bản ghi được cập nhật và một số không. Nó sẽ là tất cả hoặc không có gì và bất kể mức độ cô lập.

+0

Cảm ơn. Chỉ cần làm rõ thêm, giả sử chỉ mục 4 có khóa đọc, câu lệnh cập nhật có chờ cho khóa đọc được nâng lên để cập nhật tất cả 5 hàng không? – Ted

+0

@Ted: Trong Oracle, độc giả và nhà văn không chặn nhau. Khi dữ liệu được cập nhật, dữ liệu cũ được lưu tự động trong một thời gian (UNDO). Điều này cho phép truy vấn đọc dữ liệu tại một thời điểm, bất kể có bất kỳ thay đổi nào đang diễn ra. –

+0

@jonearles Có, nhưng các nhà văn ** làm ** chặn nhau (khi họ đang viết cho cùng một hàng). Các nhà văn sẽ khóa từng hàng, có nghĩa là có khả năng xảy ra bế tắc nếu việc viết không được thực hiện theo cùng thứ tự bởi tất cả các giao dịch. Kể từ khi UPDATE không có mệnh đề ORDER BY, một 'SELECT ... ORDER BY ... FOR UPDATE' riêng biệt phải được sử dụng để bảo đảm thứ tự khóa. –

4

Có khả năng.

Trong trường hợp này, vì bạn chỉ cập nhật 5 hàng, nên DML song song sẽ không thích hợp. Giả sử rằng UPDATE không gọi DML song song, các hàng sẽ được cập nhật tuần tự mặc dù thứ tự các hàng được cập nhật là tùy ý. INDEX 1 có thể là người đầu tiên được cập nhật, người cuối cùng được cập nhật hoặc có thể được cập nhật ở giữa. Nó phụ thuộc vào kế hoạch truy vấn.

2

CẬP NHẬT, DELETE và INSERT không có thứ tự xác định. Khái niệm họ áp dụng cho một bộ và được thực hiện tất cả cùng một lúc. Thực tế nói, không dựa vào bất kỳ chuỗi nào bạn có thể quan sát - đó là một chi tiết thực hiện có thể thay đổi, và chỉ xảy ra bởi vì thế giới thực theo cách của lý thuyết.

+0

Cảm ơn! Tôi suy ra rằng bản cập nhật được thực hiện trên cơ sở tập hợp, tức là bản cập nhật sẽ chờ tất cả các hàng có sẵn trước khi thực hiện câu lệnh cập nhật? – Ted

+0

@Ted: Oracle chặn khóa cấp, nhưng tất cả các hàng không cần phải mở khóa khi cập nhật bắt đầu. – jmoreno

0

Tất cả các bản ghi sẽ được cập nhật thành một bản ghi trong một giao dịch. Oracle không đảm bảo bất kỳ thứ tự nào trong chuỗi cập nhật.

Bạn có thể cập nhật bất kỳ trường nào bằng giá trị dbms_transaction.local_transaction_id trong bảng của bạn để kiểm tra.

Các vấn đề liên quan