2009-09-23 24 views
8

này cảm thấy giống như một câu hỏi ngớ ngẩn, nhưng tôi thấy những điều sau đây trong hướng dẫn khái niệm Oracle về quản lý giao dịch:Oracle có quay trở lại giao dịch khi có lỗi không?

Một giao dịch kết thúc khi một trong các sau đây xảy ra:

vấn đề Một người sử dụng một COMMIT hoặc Câu lệnh ROLLBACK không có mệnh đề SAVEPOINT.

Người dùng chạy câu lệnh DDL chẳng hạn như TẠO, TẠO, RENAME hoặc ALTER. Nếu giao dịch hiện tại chứa bất kỳ tuyên bố DML nào, trước tiên Oracle cam kết giao dịch , sau đó chạy và cam kết tuyên bố DDL là một giao dịch tuyên bố mới mới.

Một người dùng ngắt kết nối khỏi Oracle. Giao dịch hiện tại được cam kết.

Quy trình người dùng chấm dứt bất thường. Giao dịch hiện tại được cuộn quay lại.

Tôi có phải giải thích điểm cuối cùng có nghĩa là nếu tôi phát hành truy vấn có lỗi, giao dịch sẽ được khôi phục?

+0

Thực ra, nó giống như một câu hỏi rất thú vị đối với tôi. Postgres rollback về lỗi, và tôi thường thấy nó khó chịu (và tự hỏi nếu Oracle đã làm một cái gì đó tương tự). – jsight

+0

Hãy cho tôi biết, tại sao bạn sử dụng giao dịch nếu bạn không muốn khôi phục lỗi? Đây là một trong những mục đích chính của giao dịch. –

+0

@Oliver: Tôi không nhất thiết muốn hoặc không muốn chúng. Tôi chỉ muốn biết cách họ làm việc. –

Trả lời

7

"Quy trình người dùng" trong ngữ cảnh này đề cập đến quá trình đang chạy trên máy khách tạo kết nối tới Oracle. Nói cách khác, nếu bạn đang sử dụng Ứng dụng A (SQL*Plus, TOAD, v.v.) để kết nối với Oracle, quá trình người dùng là SQL*Plus, TOAD, v.v. Nếu quá trình người dùng đó chết trong khi bạn đang ở giữa giao dịch, giao dịch đó sẽ được khôi phục. Điều này sẽ xảy ra ngay khi PMON phát hiện ra rằng khách hàng đã chết mà có thể mất một chút thời gian-- không phải lúc nào cũng dễ dàng để Oracle phân biệt sự thất bại của quá trình người dùng từ một quá trình người dùng khoảnh khắc.

1

Tôi đồng ý với Justin, thông tin chi tiết của anh ấy là chính xác. Thêm thông tin bổ sung: Là nhà phát triển ứng dụng, bạn nên gọi lệnh rollback một cách rõ ràng nếu xảy ra lỗi. Điều này có nghĩa, bạn cũng nên xem xét việc nhóm các câu lệnh thành các khối giao dịch khi thích hợp. Khối giao dịch và rollback được xử lý khác nhau bởi các công nghệ khác nhau, nó có giá trị một số nghiên cứu để đảm bảo bạn hiểu nó tốt.

12

đây là một câu hỏi thú vị!

Khi Oracle gặp lỗi, nó sẽ khôi phục câu lệnh hiện tại, chứ không phải giao dịch. Một câu lệnh là bất kỳ lệnh mức cao nhất nào, nó có thể là một câu lệnh SQL (INSERT, UPDATE ...) hoặc một khối PL/SQL. Điều này có nghĩa là khi một câu lệnh (ví dụ một thủ tục pl/sql được gọi từ java) trả về một lỗi, Oracle sẽ đặt giao dịch ở trạng thái logic giống như trước cuộc gọi. Điều này vô cùng hữu ích, bạn không phải lo lắng về các thủ tục được thực hiện một nửa (**).

This thread on AskTom covers the same topic:

[tuyên bố] hoặc HOÀN TOÀN xảy ra hoặc nó HOÀN TOÀN KHÔNG xảy ra và cách mà làm việc là cơ sở dữ liệu không tương đương logic của:

begin 
    savepoint foo; 
    <<your statement>> 
exception 
    when others then rollback to foo; 
        RAISE; 
end; 

này tính năng, theo ý kiến ​​của tôi, là lý do tại sao nó dễ dàng hơn nhiều để viết mã cơ sở dữ liệu (*) bằng pl/sql hơn bất kỳ ngôn ngữ nào khác.

(*) mã tương tác với một DB Oracle tất nhiên, tôi cho rằng ngôn ngữ thủ tục gốc của các DBMS khác có các tính năng tương tự.

(**) Điều này chỉ liên quan đến DML kể từ DDL are not transactional trong Oracle. Hãy cẩn thận với một số gói DBMS cập nhật từ điển dữ liệu (chẳng hạn như DBMS_STATS), chúng thường thực hiện các thay đổi giống như DDL và phát hành các cam kết. Tham khảo documentation trong trường hợp nghi ngờ.

Cập nhật: hành vi này là một trong những khái niệm quan trọng nhất trong PL/SQL, tôi sẽ cung cấp một ví dụ nhỏ để chứng minh số nguyên tử của các báo cáo pl/sql:

SQL> CREATE TABLE T (a NUMBER); 

Table created 

SQL> CREATE OR REPLACE PROCEDURE p1 AS 
    2 BEGIN 
    3  -- this statement is successful 
    4  INSERT INTO t VALUES (2); 
    5  -- this statement will raise an error 
    6  raise_application_error(-20001, 'foo'); 
    7 END p1; 
    8/

Procedure created 

SQL> INSERT INTO t VALUES (1); 

1 row inserted 

SQL> EXEC p1; 

begin p1; end; 

ORA-20001: foo 
ORA-06512: at "VNZ.P1", line 5 
ORA-06512: at line 2 

SQL> SELECT * FROM t; 

     A 
---------- 
     1 

Oracle có cuộn lại giao dịch đến điểm ngay trước khi gọi p1. Không có một nửa công việc được thực hiện. Nó như thể thủ tục p1 chưa bao giờ được gọi.

+1

Bạn sai về các câu lệnh và các khối PL/SQL. Một khối PL/SQL không phải là một câu lệnh hơn INSERT, UPDATE hoặc DELETE. Nếu một khối PL/SQL ném một lỗi và không có xử lý savepoint nào giống như đoạn mã của bạn thì bạn phải lo lắng về các thủ tục được thực thi một nửa. – Christian13467

+2

Cơ đốc giáo, điều đó sai. Nếu một ngoại lệ được nâng lên bởi một khối PL/SQL mức cao nhất, như được gọi bởi một máy khách, thì có một sự quay trở lại điểm trước khi gọi ra khối đó (giả sử không có cam kết trong PL/SQL can thiệp). –

+0

@Christian: Tôi đã cập nhật câu trả lời của mình, hy vọng điều này sẽ làm rõ khái niệm mà tôi đang cố giải thích. –

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