2014-07-01 4 views
1

Oracle에서의 트랜잭션에 문제가 있습니다.oracle에서 "중첩 된"트랜잭션 사용

create or replace procedure myschema.DataSave(v_value IN NUMBER) 
as 
begin 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 

begin 
insert/update/delete... 
exception when OTHERS then goto error; 
end; 

COMMIT; 
return; 

<<error>> 
ROLLBACK; 
return; 
end; 
/

나는이 양식 C# 프로젝트에서이 프로 시저를 호출하고있다 : 좀이 같은 절차가 나는 데이터베이스에 하나의 "내부"또는 "중첩"트랜잭션을 사용하는 것을 시도하고있다 그래서

... 
string conn_str = "..."; 
OracleConnection con = new OracleConnection(conn_str); 
con.Open(); 
OracleCommand cmd = new OracleCommand("", con); 

try 
{ 
    cmd.Transaction = cmd.Connection.BeginTransaction(); 

    for (int i = 0; i < 10; i++) 
    { 
     // this condition simulates incorrect situations 
     if (i == 5) 
     { 
      throw new Exception("Something is wrong."); 
     } 

     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.CommandText = "myschema.DataSave"; 
     cmd.Parameters.Clear(); 
     cmd.Parameters.Add("v_value", OracleDbType.Int32, i, ParameterDirection.Input); 
    } 

    cmd.Transaction.Commit(); 
} 
catch (Exception ex) 
{ 
    cmd.Transaction.Rollback(); 
} 
finally 
{ 
    con.Close(); 
    con.Dispose(); 
} 
... 

응용 프로그램 계층에서 다른 "외부"트랜잭션을 생성합니다. 그러나 응용 프로그램에서 예외가 발생하면 롤백이 작동하지 않습니다 (이전에 데이터가 1,2,3,4로 남아 있음). 하지만 왜? 나는이 양식에 MSSQL 저장 프로 시저를 사용하여이 문제를 직면해야 didnt가 : 오라클의 새로운

create procedure myschema.DataSave 
@id as int 
as 
begin 

    begin transaction 

    insert/update/delete... 
    if @@error > 0 goto error 

    commit transaction 
    return 

    error: 
    rollback transaction 
    return 
end 
go 

임과 이에 대한 솔루션 silimilar을 찾을 수 couldnt한다. 누군가 내가 뭘 잘못하고 있는지 말해줘.

답변

5

오라클은 중첩 된 트랜잭션을 지원하지 않습니다. 트랜잭션이 커밋되면 커밋됩니다. 그래서 일반적으로 스토어드 프로 시저에서 트랜잭션을 커밋 (또는 롤백)하고 싶지 않으므로 트랜잭션 의미가 다른 경우 다른 곳에서 프로 시저를 재사용하기가 어렵습니다.

그러나 프로 시저의 시작 부분에 세이브 포인트를 선언하고 오류가 발생하면 해당 세이브 포인트로 롤백 할 수 있습니다. 그런 다음 커밋 제거 할 경우, 트랜잭션이 단독으로하지이 경우 데이터베이스 코드

begin 
    savepoint beginning_of_proc; 

    insert/update/delete... 

exception 
    when OTHERS then 
    rollback to beginning_of_proc; 
    raise; 
end; 

하여 응용 프로그램 코드에 의해 제어됩니다,하지만 내 바이어스는 코드에서 세이브 포인트를하지 필요하지 않는 것 롤백 (rollback)이 있어야하며, 뭔가 유용한 것을하지 않는 한 예외를 잡아서는 안된다. DML을 수행하고 예외가 발생하면 응용 프로그램에서 처리하십시오.

1

예외가에서 제기하고있는 프로그램 그룹으로 제한됩니다.

create or replace procedure myschema.DataSave(v_value IN NUMBER) 
as 

ex_dml_error EXCEPTION; 
begin 


begin 
insert/update/delete... 
exception 
    when OTHERS then ex_dml_error; 
end; 

COMMIT; 

EXCEPTION 
    WHEN ex_dml_error THEN 
    ROLLBACK; 
end; 
/