Использование «вложенных» транзакций в Oracle

1

У меня проблемы с транзакциями в 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;
/

Я вызываю эти процедуры из проекта С# в этой форме:

...
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 и хранимые процедуры в этой форме:

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

Я новичок в Oracle и не смог найти решение, подобное этому. Пожалуйста, скажите мне, что я делаю неправильно.

Теги:
plsql
transactions

2 ответа

5
Лучший ответ

Oracle не поддерживает вложенные транзакции. Если транзакция совершается, она совершает. Вот почему вы вообще не хотите совершать (или откатывать) транзакцию в хранимой процедуре, что затрудняет повторное использование процедуры в другом месте, если ваша семантика транзакции отличается.

Однако вы можете объявить точку сохранения в начале вашей процедуры и откат к этой точке сохранения в случае ошибки. Если вы удалите фиксацию, то транзакция контролируется только кодом приложения не кодом базы данных

begin
  savepoint beginning_of_proc;

  insert/update/delete...

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

В этом случае, однако, мое смещение было бы не иметь точки сохранения в коде, а не иметь откат, а не для исключения исключения, если вы не делаете что-то полезное с ним. Просто сделайте 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;
/

Ещё вопросы

Сообщество Overcoder
Наверх
Меню