Chúng tôi vừa nâng cấp từ Oracle 10 lên Oracle 11.2. Sau khi nâng cấp, tôi bắt đầu thấy một lỗi bảng đột biến gây ra bởi một hàm thay vì một trình kích hoạt (mà trước đây tôi chưa từng gặp). Đó là mã cũ đã làm việc trong các phiên bản trước của Oracle.Bảng đột biến trong Oracle 11 do một hàm
Dưới đây là một kịch bản mà sẽ gây ra lỗi:
create table mutate (
x NUMBER,
y NUMBER
);
insert into mutate (x, y)
values (1,2);
insert into mutate (x, y)
values (3,4);
tôi đã tạo ra hai hàng. Bây giờ, tôi sẽ tăng gấp đôi các hàng của mình bằng cách gọi tuyên bố này:
insert into mutate (x, y)
select x + 1, y + 1
from mutate;
Đây không phải là điều cần thiết để sao chép lỗi, nhưng nó sẽ giúp với trình diễn sau này. Vì vậy, nội dung của bảng giờ trông giống như sau:
X,Y
1,2
3,4
2,3
4,5
Tất cả đều tốt. Bây giờ cho phần thú vị:
create or replace function mutate_count
return PLS_INTEGER
is
v_dummy PLS_INTEGER;
begin
select count(*)
into v_dummy
from mutate;
return v_dummy;
end mutate_count;
/
Tôi đã tạo một hàm để truy vấn bảng và trả về một số. Bây giờ, tôi sẽ kết hợp điều đó với câu lệnh INSERT:
insert into mutate (x, y)
select x + 2, y + 2
from mutate
where mutate_count() = 4;
Kết quả? Lỗi này:
ORA-04091: table MUTATE is mutating, trigger/function may not see it
ORA-06512: at "MUTATE_COUNT", line 6
Vì vậy, tôi biết những gì gây ra lỗi, nhưng tôi tò mò như với tại sao. Oracle không thực hiện SELECT, truy xuất tập kết quả và sau đó thực hiện chèn hàng loạt các kết quả đó? Tôi sẽ chỉ mong đợi một lỗi bảng đột biến nếu các bản ghi đã được chèn trước khi truy vấn kết thúc. Nhưng nếu Oracle đã làm điều đó, sẽ không tuyên bố trước đó:
insert into mutate (x, y)
select x + 1, y + 1
from mutate;
bắt đầu một vòng lặp vô hạn?
UPDATE:
Qua liên kết Jeffrey Tôi thấy điều này trong the Oracle docs:
By default, Oracle guarantees statement-level read consistency. The set of data returned by a single query is consistent with respect to a single point in time.
Ngoài ra còn có một bình luận từ các tác giả trong his post:
One could argue why Oracle doesn't ensure this 'statement-level read consistency' for repeated function calls that appear inside a SQL statement. It could be considered a bug as far as I'm concerned. But this is the way it currently works.
Tôi thích hợp trong giả định rằng điều này hành vi đã thay đổi giữa Oracle phiên bản 10 và 11?
Liên kết tốt, cảm ơn! Tôi sẽ cập nhật câu hỏi của mình và để nó mở một chút để xem nó có tạo ra bất kỳ cuộc thảo luận bổ sung nào không. –
+1 bạn có điểm về lý do tại sao nó xảy ra – zep
Điều này đã giúp, nhưng có câu hỏi làm rõ ... Có thể hàm tồn tại trong Gói được gọi từ trình kích hoạt trước khi cập nhật không? Tôi đang có một cơn ác mộng của những vấn đề như nhiều người khác do Oracles crappy gây nên. –