Hành vi bạn gặp phải đối với FOR UPDATE SKIP LOCKED đã được mô tả trong ghi chú blog này. Sự hiểu biết của tôi là mệnh đề FOR UPDATE được đánh giá SAU mệnh đề WHERE. SKIP LOCKED giống như một bộ lọc bổ sung đảm bảo rằng trong số các hàng sẽ được trả lại, không có hàng nào bị khóa.
Câu lệnh của bạn về mặt logic tương đương với:tìm hàng đầu tiên từ card_numbers
và trả lại nếu nó không bị khóa. Rõ ràng đây không phải là điều bạn muốn.
Đây là một trường hợp thử nghiệm nhỏ mô tả lại hành vi mà bạn mô tả:
SQL> CREATE TABLE t (ID PRIMARY KEY)
2 AS SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 1000;
Table created
SESSION1> select id from t where rownum <= 1 for update skip locked;
ID
----------
1
SESSION2> select id from t where rownum <= 1 for update skip locked;
ID
----------
Không có hàng nào được trả lại từ lần chọn thứ hai. Bạn có thể sử dụng con trỏ để khắc phục sự cố này:
SQL> CREATE FUNCTION get_and_lock RETURN NUMBER IS
2 CURSOR c IS SELECT ID FROM t FOR UPDATE SKIP LOCKED;
3 l_id NUMBER;
4 BEGIN
5 OPEN c;
6 FETCH c INTO l_id;
7 CLOSE c;
8 RETURN l_id;
9 END;
10 /
Function created
SESSION1> variable x number;
SESSION1> exec :x := get_and_lock;
PL/SQL procedure successfully completed
x
---------
1
SESSION2> variable x number;
SESSION2> exec :x := get_and_lock;
PL/SQL procedure successfully completed
x
---------
2
Vì tôi đã tìm nạp con trỏ một cách rõ ràng, chỉ một hàng sẽ được trả về (và chỉ một hàng sẽ bị khóa).