2009-10-15 35 views
7

Có cách nào có thể kiểm tra nếu một hàng đã bị khóa để cập nhật trong Oracle không?Làm cách nào để kiểm tra xem một hàng có bị khóa để cập nhật không?

Như một ví dụ, giả sử các truy vấn sau đây, được thực hiện bởi một người dùng:

select * from SOME_TABLE where THE_ID = 1000 for update; 

Với người dùng khác tôi muốn kiểm tra xem hàng với THE_ID = 1000 bị khóa. Nếu tôi thử bản cập nhật hoặc thứ gì đó mà người dùng thứ hai bị chặn và vẫn đang chờ (không muốn điều đó).

Tôi cũng đã cố gắng chạy truy vấn sau đây với người sử dụng thứ hai:

select * from SOME_TABLE where THE_ID = 1000 for update NOWAIT; 

Vì tôi không thể đặt hai ổ khóa trên cùng hàng này sẽ thất bại. Và nó có. Tôi nhận được một "ORA-00054: tài nguyên bận rộn và có được với lỗi được chỉ định NOWAIT". Tôi có thể luôn dựa vào lỗi này để kiểm tra sự hiện diện của khóa hay không, có cách nào đơn giản và rõ ràng hơn để xác định xem hàng có bị khóa không?

Cảm ơn bạn!

+1

bạn nên nhận được lỗi này "ORA-00054: tài nguyên bận rộn và có được với NOWAIT được chỉ định" - bạn có chắc chắn người dùng của mình có thể xem bảng không? – SeriousCallersOnly

+0

@ SeriousCallersOnly: Cảm ơn, tôi thực sự đang có “ORA-00054: tài nguyên bận rộn và có được lỗi NOWAIT được chỉ định”. ORA-00942 được một lớp ứng dụng khác của tôi ném. Xin lỗi vì điều đó. Tôi sẽ chỉnh sửa câu hỏi. –

Trả lời

14

Bạn có thể viết một thủ tục với FOR UPDATE NOWAIT và trả về một thông báo lỗi khi hàng đã bị khóa,

SQL> CREATE OR REPLACE PROCEDURE do_something(p_id NUMBER) IS 
    2  row_locked EXCEPTION; 
    3  PRAGMA EXCEPTION_INIT(row_locked, -54); 
    4 BEGIN 
    5  FOR cc IN (SELECT * 
    6     FROM some_table 
    7     WHERE ID = p_id FOR UPDATE NOWAIT) LOOP 
    8  -- proceed with what you want to do; 
    9  NULL; 
10  END LOOP; 
11 EXCEPTION 
12  WHEN row_locked THEN 
13  raise_application_error(-20001, 'this row is locked...'); 
14 END do_something; 
15/

Procedure created 

Bây giờ chúng ta hãy xây dựng một ví dụ nhỏ với hai phiên:

session_1> select id from some_table where id = 1 for update; 

     ID 
---------- 
     1 

session_2> exec do_something(1); 

begin do_something(1); end; 

ORA-20001: this row is locked... 
ORA-06512: at "VNZ.DO_SOMETHING", line 11 
ORA-06512: at line 2 

session_1> commit; 

Commit complete 

session_2> exec do_something(1); 

PL/SQL procedure successfully completed 
+0

Như tôi đã trả lời cho SeriousCallersOnly Tôi thực sự gặp lỗi ORA-00054. Cảm ơn bạn. Nhưng tôi có thể dựa vào nó để kiểm tra khóa không? –

+0

@dpb: bạn có thể dựa vào cơ chế này. Tôi đã thêm một ví dụ nhỏ cho thấy quy trình sẽ hoạt động như thế nào với hai phiên khóa cùng một hàng. –

1

Nó không đơn giản và không sạch sẽ, nhưng thông tin có sẵn trong các chế độ xem V$LOCKV$SESSION.

Tuy nhiên, nếu bạn cảm thấy cần phải sử dụng một cái gì đó như thế này như là một phần của mã ứng dụng bình thường của bạn, bạn cần phải suy nghĩ lại. Các ứng dụng không nên quan tâm đến cách cơ sở dữ liệu khóa. Nếu bạn đang chạy vào deadlocks, bạn cần phải cơ cấu lại các truy vấn của bạn để chúng không xảy ra.

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