Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Có thể xảy ra bế tắc với cùng một phương thức truy cập không?

"Thứ tự" mang tính xác định theo quan điểm của bạn chỉ khi bạn bao gồm ORDER BY trong truy vấn của mình. Cho dù nó là xác định từ quan điểm của máy chủ là một chi tiết triển khai, không nên dựa vào.

Đối với khóa, hai câu lệnh DML giống nhau có thể chặn (nhưng không khóa) lẫn nhau. Ví dụ:

CREATE TABLE THE_TABLE (
    ID INT PRIMARY KEY
);

Giao dịch A:

INSERT INTO THE_TABLE VALUES(1);

Giao dịch B:

INSERT INTO THE_TABLE VALUES(1);

Tại thời điểm này, Giao dịch B bị đình trệ cho đến khi Giao dịch A cam kết hoặc quay trở lại. Nếu A cam kết, B không thành công vì vi phạm CHÍNH. Nếu A quay ngược trở lại, B thành công.

Các ví dụ tương tự có thể được xây dựng cho CẬP NHẬT và XÓA.

Điểm quan trọng là việc chặn sẽ không phụ thuộc vào kế hoạch thực thi - bất kể Oracle chọn cách nào để tối ưu hóa truy vấn của bạn, bạn sẽ luôn có cùng một hành vi chặn. Bạn có thể muốn đọc về Khóa tự động trong Hoạt động DML để biết thêm thông tin.

Đối với chết -locks, chúng có thể đạt được với nhiều câu lệnh. Ví dụ:

A: INSERT INTO THE_TABLE VALUES(1);
B: INSERT INTO THE_TABLE VALUES(2);
A: INSERT INTO THE_TABLE VALUES(2);
B: INSERT INTO THE_TABLE VALUES(1); -- SQL Error: ORA-00060: deadlock detected while waiting for resource

Hoặc, có thể với các câu lệnh sửa đổi nhiều hàng theo thứ tự khác nhau và một số thời điểm không may mắn (có ai có thể xác nhận điều này không?).

--- CẬP NHẬT ---

Để trả lời cập nhật cho câu hỏi của bạn, hãy để tôi quan sát chung:Nếu các chuỗi thực thi đồng thời khóa các đối tượng theo thứ tự nhất quán , bế ​​tắc là không thể. Điều này đúng với bất kỳ loại khóa nào, có thể là mutexes trong chương trình đa luồng trung bình của bạn (ví dụ:xem suy nghĩ của Herb Sutter về Lock Hierarchies) hoặc có thể là cơ sở dữ liệu. Khi bạn thay đổi thứ tự theo cách mà hai ổ khóa bất kỳ bị "lật", thì nguy cơ bế tắc sẽ xuất hiện.

Nếu không quét chỉ mục, bạn đang cập nhật ( và khóa ) hàng trong một thứ tự và với chỉ mục trong một thứ tự khác. Vì vậy, đây có thể là những gì xảy ra trong trường hợp của bạn:

  • Nếu bạn tắt tính năng quét chỉ mục cho cả hai giao dịch đồng thời , cả hai đều khóa các hàng theo cùng một thứ tự [X], do đó, không thể xảy ra bế tắc.
  • Nếu bạn bật quét chỉ mục cho chỉ một giao dịch , chúng không còn khóa các hàng theo cùng một thứ tự, do đó có khả năng dẫn đến bế tắc.
  • Nếu bạn bật quét chỉ mục cho cả hai giao dịch , thì một lần nữa cả hai đều đang khóa các hàng theo cùng một thứ tự và không thể xảy ra bế tắc (hãy tiếp tục và thử alter session set optimizer_index_cost_adj = 1; trong cả hai phiên và bạn sẽ thấy).

[X] Mặc dù tôi sẽ không dựa vào việc quét toàn bộ bảng có thứ tự đảm bảo - đó có thể chỉ là cách hoạt động của Oracle hiện tại trong những trường hợp cụ thể này và một số Oracle trong tương lai hoặc các trường hợp khác có thể tạo ra hành vi khác.

Vì vậy, sự hiện diện của chỉ mục là ngẫu nhiên - vấn đề thực sự đang đặt ra. Điều này xảy ra là việc đặt hàng trong CẬP NHẬT có thể bị ảnh hưởng bởi một chỉ mục, nhưng nếu chúng ta có thể tác động đến việc đặt hàng theo cách khác, chúng ta sẽ nhận được kết quả tương tự.

Vì UPDATE không có ORDER BY, bạn không thể thực sự đảm bảo thứ tự khóa bằng cách UPDATE một mình. Tuy nhiên, nếu bạn tách rời khóa cập nhật, sau đó bạn có thể đảm bảo thứ tự khóa:

SELECT ... ORDER BY ... FOR UPDATE;

Mặc dù mã gốc của bạn gây ra sự cố trong môi trường Oracle 10 của tôi, nhưng đoạn mã sau thì không:

Phiên 1:

declare
    cursor cur is select * from deadlock_test where a > 0 order by a for update;
begin
    while true loop
        for locked_row in cur loop
            update deadlock_test set a = -99999999999999999999 where current of cur;
        end loop;
        rollback;
    end loop;
end;
/

Phiên 2:

alter session set optimizer_index_cost_adj = 1;

declare
    cursor cur is select * from deadlock_test where a > 0 order by a for update;
begin
    while true loop
        for locked_row in cur loop
            update deadlock_test set a = -99999999999999999999 where current of cur;
        end loop;
        rollback;
    end loop;
end;
/


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Oracle LEFT JOIN và lỗi SUBQUERY:ORA-00905:thiếu từ khóa

  2. Liệt kê tất cả các trình kích hoạt trong Cơ sở dữ liệu Oracle

  3. Thực hành tốt để mở / đóng các kết nối trong ứng dụng asp.net?

  4. Các câu lệnh DDL có luôn cung cấp cho bạn một cam kết ngầm hay bạn có thể nhận được một lần khôi phục ngầm không?

  5. Oracle Date TO_CHAR ('Tháng DD, YYYY') có thêm khoảng trắng trong đó