When does an autonomous transaction end for Oracle? - oracle

As I understand autonomous transactions (in the Oracle world), the autonomous transaction ends when a commit or rollback is issued. However, I have just written a procedure as an autonomous transaction because I needed to isolate a piece of DDL that changes a tablespace from read only to read write.
Then I started thinking about when the autonomous bit ended.
The problem is that there is an implicit commit both before and after the DDL is executed. Now, I happen to know that my code has the desired effect, so I can only surmise that the initial 'empty' commit is not the end of the autonomous transaction and the subsequent commit is. What is surprising is that I cannot find any mention of this on the internet.
Can anyone point me towards documentation that would explain my conundrum?

A routine declared autonomous is autonomous for the whole routine and doesn't end when a commit or rollback is issued.
See here in oracle docs:

Related

Is commit required in an Oracle stored procedure which is called from Java class?

I have an Oracle Stored Procedure that does some inserts and updates on a table in DB.
There is no explicit Commit or Rollback statement at the end of the procedure.
However, when I call this SP through a java class, I see that the inserts and updates are committed into the DB.
So can anyone help me understand if we really need a commit statement at the end of the stored procedure in Oracle?
I am not java experience but as far as I know when you close the connection of the database the data are committed (unless if you rollback them). Now to return into your question is when to use the commit in SP.
When you use DML(insert,update,delete) operation in the procedure on a table, the table will be Locked therefore if any other user try to access the locked table, it has to wait till you commit/rollback your operation. so if your procedure was taking time, due to a long loop or bad optimized query then the user will be blocked. So if you had a commit before the DMl, the no blocks will happen.
Other reason, is the undo tablespace, where all the data not committed will wait there till you commit them, so if for example you inserted lot of data (millions), your undo might get full depend on your size and youll get an error.
so short answer , if your procedure doesn't has lot of operations on big tables and it fast then you can pass by the commit , otherwise it better to add commits.

Oracle: What is a transaction?

I'm new to Oracle so I'm still learning the basics. Can someone explain to me what a transaction is? When I look it up it always seems to contain an update statement but is this a necessary feature? How is it declared? How is it any different to anonymous block?
Any help in explaining this would be much appreciated!
A transaction is a logical unit of work that contains one or more SQL statements. A transaction is an atomic unit. The effects of all the SQL statements in a transaction can be either all committed (applied to the database) or all rolled back (undone from the database).
A transaction begins with the first executable SQL statement. A transaction ends when it is committed or rolled back, either explicitly with a COMMIT or ROLLBACK statement or implicitly when a DDL statement is issued.

Why is it not allowed to use a ROLLBACK statement in a PL/SQL trigger, but RAISE_APPLICATION_ERROR is?

Correct me if I'm wrong, but I was under the impression that a call to RAISE_APPLICATION_ERROR() forces a ROLLBACK. How is it possible that a call to RAISE_APPLICATION_ERROR() is allowed in PL/SQL triggers when ROLLBACK statements and/or methods that execute ROLLBACK statements are not?
I have the feeling I am missing a crucial point here :)
Thanks in advance!
Consider yourself corrected. Sort of. Raising (or encountering) an exception doesn't cause a rollback of the curent transaction. From the documentation:
In most cases, if a trigger runs a statement that raises an exception, and the exception is not handled by an exception handler, then the database rolls back the effects of both the trigger and its triggering statement.
Note that it's the statement, not the transaction; but "roles back the effect of" is a little confusing I suppose...
There is an implicit savepoint around every statement, and the trigger exception rolls back to that savepoint (except for after triggers etc. as noted in the docs). From Tom Kyte's Expert Oracle Database Architecture:
Oracle achieves this statement-level atomicity by silently wrapping a SAVEPOINT aroind each of our calls to the database.
Inside a trigger a RAISE_APPLICATION_ERROR does not perform a ROLLBACK, it aborts the current operation, i.e. a single UPDATE/INSERT/DELETE. Everything inside a trigger belongs to such an operation (thats' also the reason for famous error "ORA-04091 - Table is mutating, trigger/function may not see it").
A Rollback reverts all changes within current transaction (or up to given Savepoint), that's different.

What can i do in Oracle in order to preserve the savepoint if internal commit occurs?

background:
i'm doing some Oracle plsql refactoring; The first think that i want to accomplish is to have unit test for the principal components.
For this i'm using ruby with the gem plsq-spec https://github.com/rsim/ruby-plsql-spec
In order to execute the tests several times, i'm using Oracle Savepoints after open the database conection, and doing a rollback to the savepoint before close the connection
Problem:
Some test can't be executed more than one time, because some procedures had internal commits.
What can i do in Oracle in order to preserve the savepoint if internal commit/rollback occurs?
With this information in the note apparently what I want is impossible
http://docs.oracle.com/cd/B19306_01/appdev.102/b14261/savepoint_statement.htm
A simple rollback or commit erases all savepoints. When you roll back
to a savepoint, any savepoints marked after that savepoint are erased.
The savepoint to which you roll back remains.
so, the only solutions are?:
modify the procedures
erase all data before execute the tests?
tks
The Flashback feature may help you here, as you can restore the database or individual tables to their state as-of a previous point in time.
http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9012.htm

Do the time of the COMMIT and ROLLBACK affect performance?

Suppose I have a set of ID . For each ID , I will insert many records to many different tables based on the ID .Between inserting difference tables, different business checks will be called . If any checking fail , all the records that are inserted based on this ID will be ROLLBACK .This bulk insert action is done through using PL/SQL . Do the time of the COMMIT and ROLLBACK affect the performance and how does it affect ? For example , should I COMMIT after finish the process for one ID or COMMIT after finish all ID?
This is not so much of a performance decision but a process design decision. Do you want the other IDs to stay in the database when you have to roll back a faulty ID?
For obvious reasons, rollback takes longer when more rows must be rolled back. Rollback usually takes longer (sometimes much longer!) than the operations that have to be rolled back. Commit is always fast in Oracle, so it probably doesn't matter how often you commit in that regard.
Your problem description indicates you have a large set of smaller logical transactions (each new ID is a transaction). You should commit each logical transaction. The two reasons to wait to commit the entire set of transactions are:
If the entire set of transactions is in fact a transaction itself - all inserts must succeed for any rows to be committed. In that context, your smaller "transactions" aren't truly transactions.
You don't have a restart capability in your bulk load process, which in effect makes this a special case of item 1. If your bulk load process aborts, you need a way to skip successfully applied ID's.
Tom Kyte's advice is to commit each logical unit of work - the transaction.
Don't take the transaction time longer. make it short as possible as you can. Because according to your query some locks have been created. This locks may cause perfomance issues... so do it ID by ID...
There are two "forces" at work....
locking
during your open transaction, oracle puts locks on the changed rows.
whenever another transaction needs to update any of the locked rows,
it has to wait.
in the worst case, you can even build a deadlock.
synchronous write
every commit performs a synchronous write.
(there are ways to disable that, but it is usually the thing everybody wants: integrity).
that synchronous write can take (much) longer then the a regular write (that can be buffered).
Not to forget that there is usually an additional network round trip involved with an commit.
so, the one force says "commit as soon as possible (considering your integrity requirements)" the other says "commit as as less often as possible".
There are some other issues to consider as well, e.g. the maximum transaction size. every uncommited transaction needs some temporary space. the bigger the transaction gets, the more you need. You can also run into ORA-01555 "snapshot too old".
If there is any advice to give, then it is to implement a configurable "commit frequency" so that you can easily change it as needed.
One option if you need to control the individual sets but retain the ability to commit or rollback the entire transaction is to use savepoints. You can set a savepoint at the beginning of the outermost loop, then rollback to it if an error occurs. You might end up with something like this:
begin
--Initial batch logging
for r_record in cur_cursor loop
savepoint s_cursor loop;
begin
--Process rows
exception
when others then
rollback to s_cursor;
end;
end loop;
--Final batch logging
exception
when others then
rollback;
raise;
end;

Resources