2009-09-22 31 views
5

Tôi đang làm việc trên một ứng dụng web được kết nối với oracle. Chúng tôi có một bảng trong oracle với một cột "kích hoạt". Chỉ có một hàng có thể đặt cột này thành 1 tại một thời điểm bất kỳ. Để thực thi điều này, chúng tôi đã sử dụng mức cô lập SERIALIZED trong Java, tuy nhiên chúng tôi đang chạy vào lỗi "không thể tuần tự hóa giao dịch" và không thể giải thích tại sao.ĐỌC KẾT NỐI mức cô lập cơ sở dữ liệu trong oracle

Chúng tôi đã tự hỏi liệu mức độ cô lập của READ COMMITTED có thực hiện công việc hay không. Vì vậy, câu hỏi của tôi là thế này:

Nếu chúng ta có một giao dịch mà liên quan đến SQL sau:

SELECT * 
FROM MODEL; 

UPDATE MODEL 
SET ACTIVATED = 0; 

UPDATE MODEL 
SET ACTIVATED = 1 
WHERE RISK_MODEL_ID = ?; 

COMMIT; 

Do đó, có thể cho nhiều hơn một trong các giao dịch này được thực hiện cùng một lúc, sẽ nó có thể cho nhiều hơn một hàng MODEL để có cờ kích hoạt được đặt thành 1?

Mọi trợ giúp sẽ được đánh giá cao.

Trả lời

3

giải pháp của bạn sẽ hoạt động: bản cập nhật đầu tiên của bạn sẽ khóa toàn bộ bảng. Nếu một giao dịch khác không được hoàn thành, bản cập nhật sẽ đợi. Bản cập nhật thứ hai của bạn sẽ đảm bảo rằng chỉ có một hàng sẽ có giá trị 1 vì bạn đang khóa bảng (nó không ngăn chặn các câu lệnh INSERT).

Bạn cũng nên đảm bảo rằng hàng có số RISK_MODEL_ID tồn tại (hoặc bạn sẽ có hàng không có giá trị '1' ở cuối giao dịch của mình).

Để ngăn chặn các câu lệnh INSERT đồng thời, bạn sẽ LOCK bảng (trong chế độ ĐỘC QUYỀN).

+0

tương tự, nhưng tôi muốn KHÓA MODEL trong chế độ ĐỘC QUYỀN và làm một CẬP NHẬT MODEL SET ACTIVATED = 0 Ở ĐÂU kích hoạt = 1 Ít hàng được cập nhật, vì vậy nó là hơi nhiều performant, và TABLE KHÓA sẽ ngăn chặn các hoạt động đồng thời trên bàn. –

3

Bạn có thể xem xét sử dụng một độc đáo, chức năng chỉ số dựa để cho Oracle xử lý các khó khăn chỉ có một hàng một với cờ kích hoạt thiết lập để 1.

CREATE UNIQUE INDEX MODEL_IX ON MODEL (DECODE(ACTIVATED, 1, 1, NULL)); 

Điều này sẽ ngăn chặn nhiều hơn một dòng có cờ được đặt thành 1, nhưng không có nghĩa là luôn có một hàng có cờ được đặt thành 1.

+0

+1: đơn giản, hiệu quả, đa người dùng an toàn –

2

Nếu bạn muốn đảm bảo rằng chỉ có một giao dịch có thể chạy cùng lúc thì bạn có thể sử dụng cú pháp FOR UPDATE. Vì bạn có một hàng duy nhất cần khóa này là một cách tiếp cận rất hiệu quả.

declare 
    cursor c is 
     select activated 
     from model 
     where activated = 1 
     for update of activated; 
    r c%rowtype; 
begin 
    open c; 
    -- this statement will fail if another transaction is running 
    fetch c in r; 
    .... 
    update model 
    set activated = 0 
    where current of c; 

    update model 
    set activated = 1 
    where risk_model_id = ?; 

    close c; 

    commit; 
end; 
/

commit giải phóng khóa.

Hành vi mặc định là đợi cho đến khi hàng được giải phóng. Nếu không, chúng tôi có thể chỉ định NOWAIT, trong trường hợp này, bất kỳ phiên nào khác cố cập nhật hàng hiện hoạt sẽ không thành công ngay lập tức hoặc chúng tôi có thể thêm tùy chọn WAIT với thời gian bỏ phiếu. NOWAIT là tùy chọn để chọn hoàn toàn tránh rủi ro bị treo và cũng cho chúng tôi cơ hội thông báo cho người dùng rằng ai đó đang cập nhật bảng mà họ có thể muốn biết.

Cách tiếp cận này có thể mở rộng nhiều hơn là cập nhật tất cả các hàng trong bảng. Sử dụng chỉ mục dựa trên chức năng như WW cho thấy để thực thi quy tắc chỉ có một hàng có thể có ACTIVATED = 1.

+0

+1: giải pháp tốt đẹp –

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