Oracle: What is a transaction? - oracle

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.

Related

PostgreSQL vs. Oracle default transaction management

In PostgreSQL, if you encounter an error in transaction (for example when your insert statement violates unique constraint), the whole transaction is aborted, you cannot commit it and no rows are inserted:
database=# begin;
BEGIN
database=# insert into table (id, something) values ('1','whatever');
INSERT 0 1
database=# insert into table (id, something) values ('1','whatever');
ERROR: duplicate key value violates unique constraint "table_id_key"
Key (id)=(1) already exists.
database=# insert into table (id, something) values ('2','whatever');
ERROR: current transaction is aborted, commands ignored until end of transaction block
database=# rollback;
database=# select * from table;
id | something |
-----+------------+
(0 rows)
You can change that by setting ON_ERROR_ROLLBACK to "on" or "interactive", after that you can do multiple inserts ignoring errors, commit and have only successfully inserted rows in table after transaction end.
database=# \set ON_ERROR_ROLLBACK interactive
In Oracle, this is the default transaction management behaviour, which surprises me. Isn't this completely counterintuitive and dangerous?
When I start a transaction I want to be sure that all the statements were successfull. What if my multiple inserts comprise some kind of an object or data structure? I end up completely unaware of the data state in my database and should be checking it after the commit.
If one of the inserts fails I want to be sure that other inserts will be rollbacked or not even evaluated after the first error, which is exactly how it's done in PostgreSQL.
Why does Oracle have such way of transaction management as a default, and why is it considered good practice?
For example, some random guy here in comments
This is a very neat feature.
I don't understand this, though: "Normally, any error you make will
throw an exception and cause your current transaction to be marked as
aborted. This is sane and expected behavior..."
No, it's really not. Oracle doesn't work this way, nor does MySQL. I
have no experience with MSSQL or DB2 but I'll bet a dollar each they
don't work this way either. There no intuitive reason why a syntax
error, or any other error for that matter, should abort a transaction.
I can only assume there's either some limitation deep in the Postgres
guts that requires this behavior, or that it conforms to some obscure
part of the SQL standard that everyone else sensibly ignores. There's
certainly no API / UX reason why it should work this way.
We really shouldn't be too proud of any workarounds we've developed
for this pathological behavior. It's like IT Stockholm Syndrome.
Does not it violate even the definition of the transaction?
Transactions provide an "all-or-nothing" proposition, stating that
each work-unit performed in a database must either complete in its
entirety or have no effect whatsoever.
I agree with you. I think it's a mistake not to abort the whole tx. But people are used to that, so they think it's reasonable and correct. Like people who use MySQL think that the DBMS should accept 0000-00-00 as a date, or people using Oracle expect that '' IS NULL.
The idea that there's a clear distinction between a syntax error and something else is flawed.
If I write
BEGIN;
CREATE TABLE new_customers (...);
INSET INTO new_customers (...)
SELECT ... FROM customers;
DROP TABLE customers;
COMMIT;
I don't care that it's a typo resulting in a syntax error that caused me to lose my data. I care that the transaction didn't successfully execute all its statements but still committed.
It'd be technically feasible to allow soft rollback in PostgreSQL before any rows are actually written by a statement - probably before we even enter the executor. So failures in the parse and parameter binding phases could allow the tx not to be aborted. We have a statement memory context we could use to clean up.
However, once the statement starts changing rows, it's doing so on disk with the same transaction ID as the prior statements in the tx. So you can't roll it back without rolling back the whole tx. To allow statement rollback Pg needs to assign a new subtransaction ID. That costs resources. You can do it explicitly with SAVEPOINTs when you want to, and internally that's what psql is doing. In theory we could allow the server to do this implicitly for each statement to implement statement rollback, just at a performance cost. But I doubt any patch implementing this would get committed, at least not without a LOT of argument, because most of the PostgreSQL team are (IMO reasonably) not fond of "whoops, that broke but we'll continue anyway" transaction semantics.

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.

When does an autonomous transaction end for 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:

oracle Transactions

is it possible to have only DDL statements with a transaction? and if so, is it possible to get it rollback to the original state, if any one of the DDL statement fails?
Thanks & Regards,
priya.R
in Oracle a DDL statement implicitely commits before and after the statement. Each statement is an independant transaction and you won't be able to rollback a successful statement.
A DDL statement however is always atomic: it either succeeds entirely or fails entirely.

triggers statement level atomicity

What does Oracle mean by "statement level atomicity"?
Let's cite a couple of chapters from the Concepts:
Statement-Level Read Consistency
Oracle always enforces statement-level read consistency. This guarantees that all the data returned by a single query comes from a single point in time--the time that the query began. Therefore, a query never sees dirty data nor any of the changes made by transactions that commit during query execution. As query execution proceeds, only data committed before the query began is visible to the query. The query does not see changes committed after statement execution begins.
Statement-Level Rollback
If at any time during execution a SQL statement causes an error, all effects of the statement are rolled back. The effect of the rollback is as if that statement had never been run. This operation is a statement-level rollback.
A SQL statement that fails causes the loss only of any work it would have performed itself. It does not cause the loss of any work that preceded it in the current transaction.
It means that any single SQL statement you run is atomic in nature - it will either succeed completely or fail completely. If your SQL statement fails, and triggers that would have run as a result of that SQL statement will fail as well.
This is a statement about the nature of transactions: a Unit Of Work either succeeds or completes in its entirety. If your transaction comprises two inserts plus an update, and the update statement fails, the database will rollback all three statements. Any recursive SQL or other SQL such as that included in triggers is included in the atomic scope of the transaction. Find out more.
Atomicity means the A in the ACID principles of transaction management.

Resources