Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Autonomous and Distributed Transactions in Oracle 8i/9i Nandeep Nagarkar 1. Introduction This article presents a basic introduction to transaction processing in PL/SQL and primarily focuses on the Autonomous transaction processing feature of PL/SQL and the changes that have occurred from Oracle 8i (8.1.7) to 9i (9.2.0.1.0). In the following sections, I will define transaction and describe the use of distributed transactions and autonomous transactions, followed by a special case, the combined use of distributed and autonomous transactions, and the changes introduced in Oracle9i. 2. Transaction Defined The simple definition of a transaction in a DBMS is to ADD, DELETE or UPDATE rows in the database. The ANSI/ISO SQL standard definition of a transaction is a logical unit of work that comprises all the executable SQL statements executed by a single user that ends when an explicit COMMIT or ROLLBACK statement is issued by the user. Transactions can be of 3 types: 1) Non-Distributed transactions, which manipulate or query only a single database (the local database where the user is logged in). 2) Distributed transactions, which manipulate or query more than one node in a distributed database. 3) Remote transactions, which manipulate or query only a remotely located database. 3. Distributed Transaction Defined Unlike the non-distributed transactions that involve SQL statements against a single node of a database (the local node where the user is logged in), the Distributed transaction involves all DML (Data Manipulation Language) operations on two or more nodes of a distributed database. Example 1 /* The distributed transaction starts from here */ INSERT INTO local. account_header (account_id, customer_id, account_type, acct_start_date) VALUES (1010,'C123','SB', SYSDATE); INSERT [email protected] (account_id, customer_id, account_type, acct_start_date) VALUES (1010,'C123','SB', SYSDATE); COMMIT; /* The distributed transaction ends after the COMMIT that follows the INSERT statement */ The transaction in this case consists of two DML statements -- one DML in the local database and the next in the remote database identified by us.remotedb.com 4. Autonomous Transaction Defined In PL/SQL, transaction processing takes place serially. That is, a new transaction can begin only when the earlier transaction ends, in which case the user issues an explicit Commit or Rollback statement. Quite often, however, your application may require you to commit or rollback changes without affecting the main transaction in the session. For example, consider a simple banking transaction in which a customer transfers funds from one account to another account. A single commit or rollback should end this transaction. (Obviously! The customer may not find it pleasant to see one of his accounts debited but the other show no credits in the case of some unexpected failure.) However, your application requires recording each activity (on each of the accounts) in a transaction history table located in a remote database. Thus, your main transaction would debit the customer's account (A) with the specified transaction amount, record the transaction activity (an autonomous transaction whose commit should not affect the main transaction), and then credit account (B) with the new amount, record the update and then commit the main transaction. From PL/SQL 8.1 onwards it is possible to achieve the goal of having to rollback some change in the main transaction while committing the log entry (the transaction history) by the issuing the PL/SQL compiler directive AUTONOMOUS_TRANSACTION. In order to use autonomous transactions, you simply have to include the following statement in your declaration section: PRAGMA AUTONOMOUS_TRANSACTION Example 2 CREATE OR REPLACE PROCEDURE log_acct_txn ( p_acct_id IN NUMBER, p_txn_type IN VARCHAR2, p_txn_amount IN NUMBER) IS PRAGMA AUTONOMOUS_TRANSACTION; acct_id account_header.account_id%type; txn_type VARCHAR2(4); txn_amount NUMBER; BEGIN INSERT INTO [email protected] ( account_id, txn_type,amount, txn_date) VALUES (acct_id,cr_type,txn_amount,SYSDATE); COMMIT; END; The block in this example now becomes an independent transaction, and the COMMIT issued in this block will not affect the SQL statements in the main transaction. When you call this procedure log_acct_txn in a block, it acts as an independent block of code and suspends the Main transaction. The main transaction will resume once the procedure completes execution. 5. Rules of Autonomous Transaction Typically, a program block can be made an autonomous transaction as shown in the preceding examples. However, some rules to follow in using autonomous transactions are: 1. Nested blocks cannot be declared as autonomous transactions. Example 3 DECLARE acct_id NUMBER; BEGIN declare pragma autonomous_transaction; begin Insert [email protected] (account_id, customer_id, account_type, acct_start_date) values (1010,'C123','SB', SYSDATE); commit; end; END; results in the following error: PLS-00710: PRAGMA AUTONOMOUS_TRANSACTION cannot be declared here. 2. An autonomous transaction must have a COMMIT or a ROLLBACK statement before it completes execution. Otherwise the following error is generated: ORA-06519: active autonomous transaction detected and rolled back. 3. As the autonomous transaction is an independent transaction, you cannot rollback to a savepoint defined in the main transaction. If you attempt to do so, you will receive the error: ORA-01086: savepoint ' specified savepoint' never established. 4. Again, calling one autonomous transaction in the main transaction in your session implies the session is concurrently running two sessions and so on. The maximum number of such concurrent transactions in your session is determined by the Oracle initialization parameter file (init.ora) parameter TRANSACTIONS. If you use a large number of autonomous transaction programs in your application that exceed the value set for the parameter, you will run into the following error: ORA-01574: maximum number of concurrent transactions exceeded. 5. You cannot declare a package as an autonomous transaction to make all procedures/functions as autonomous transactions. If you do so, you will get this error: PLS-00710: PRAGMA AUTONOMOUS_TRANSACTION cannot be declared here. 6. Finally, if your autonomous transaction tries to access a resource held by the main transaction that is suspended, it will result in a deadlock situation giving the error: ORA-00054: resource busy and acquire with NOWAIT specified. 6. Using Autonomous Transactions within a Distributed Transaction Consider a scenario where you have a distributed transaction in which you require to commit or rollback a change in a remote table followed by an insert/update/query on your local database, or vice versa. In such a case, you would most likely take advantage of the autonomous feature described in the preceding section. Example 4 /* A simple example that I have tested on Oracle8.1.7 and Oracle 9.2.0.1.0) */ /* Debit the customer's account only if the minimum balance limit is met else rollback. However, record the activity. */ DECLARE var1 NUMBER; var2 NUMBER; BEGIN --SQL statements …. --- /* The procedure debits the amount from the account but does not commit/rollback any changes */ debit_acct (acct_id, txn_amount) ; /* Calling the autonomous transaction that is shown in the preceding example to log the activity in a remote table txn_history */ log_acct_txn ( acct_id , txn_type , txn_amount) ; /* Once again query a local table */ IF min_bal_maintained(acct_id) THEN COMMIT; ELSE ROLLBACK; END IF; -more statements -END; When this example is executed in Oracle8.1.6/8.1.7, it will result in the error: ORA-00164: autonomous transaction disallowed within distributed transaction This is because Oracle8i does not support autonomous transactions within a distributed query. In Oracle 8.1.7, one of the ways to work around the limitation is to use the control statement SET TRANSACTION READY ONLY in your programs. However, the use of the SET TRANSACTION READ ONLY control statement means only a SELECT statement can follow the autonomous transaction and no other DML is permitted. Using SET TRANSACTION READ ONLY just after the BEGIN statement will not give any errors as the transaction is made READ ONLY and, as a result, no changes are made to the remote database. 7. New in Oracle9i (9.2.0) As of version 9.2.0 of Oracle9i, this limitation has been removed to a limited extent. Example 4 in the preceding section, when run in Oracle 9i (9.2.0), will not give you any errors. ORA-00164 is now redefined to: ORA-00164 distributed autonomous transaction disallowed within migratable distributed transaction In oracle 9i (9.2.0), this error is now defined in context to the use of Oracle XA library with Transaction Monitors (TM). Normally, Oracle acts as its own TM and manages its own commit and recovery. However, it also provides for using a standards-based TM. Essentially, Oracle 9.2.0 has changed the way it treats the boundaries of a transaction between its own role as a TM and that of an external TM. The concepts of migratable transactions and transaction monitors will be discussed in detail in future articles.