In this case, the DBA may use the DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY procedure to clean up any entries whose state is not "prepared." The following table indicates what the various states indicate about the transaction and what the DBA actions should be. State Column State of Global Transaction State of Local Transaction Normal DBA Action Alternative DBA Action Collecting Rolled back Rolled back None PURGE_LOST_DB_ENTRY[1] Committed Committed Committed None PURGE_LOST_DB_ENTRY Prepared Unknown Unknown None COMMIT_FORCE or ROLLBACK_FORCE Forced commit Unknown Committed None PURGE_LOST_DB_ENTRY Forced rollback Unknown Rolled back None PURGE_LOST_DB_ENTRY Forced commit (mixed) Mixed Committed [2] Forced rollback (mixed) Mixed Rolled back [1] Use only if significant reconfiguration has occurred so that automatic recovery cannot resolve the transaction. Examples are total loss of the remote database, reconfiguration in software resulting in loss of two−phase commit capability, or loss of information from an external transaction coordinator such as a TP monitor. [2] Examine manual action to remove inconsistencies, then use the PROCEDURE_PURGE_MIXED. The xid argument must be set to the value of the LOCAL_TRAN_ID column in the DBA_2PC_PENDING table. For more information on this topic, see "Manually Overriding In−Doubt Transactions" in the Oracle Corporation document Oracle8 Server Distributed Systems, and the dbmsutil file under comments for PURGE_LOST_DB_ENTRY. 4.2.7 Returning Transaction Identifiers The functions described in this section return indentifiers used by DBMS_TRANSACTION. 4.2.7.1 The DBMS_TRANSACTION.LOCAL_TRANSACTION_ID function The LOCAL_TRANSACTION_ID function returns the unique identifier for the current transaction. The specification for the function follows: FUNCTION DBMS_TRANSACTION.LOCAL_TRANSACTION_ID (create_transaction IN BOOLEAN := FALSE) RETURN VARCHAR2; The create_transaction parameter specifies whether to create a new transaction or use the current one. The function returns NULL if there is no current transaction. So in your session, the transaction ID begins as NULL and is assigned a value upon first DML operation (transaction initiation). Transaction closure (COMMIT or ROLLBACK) nullifies the transaction ID. Explicit [Appendix A] What's on the Companion Disk? 4.2.7 Returning Transaction Identifiers 231 transaction initiation (passing TRUE for second argument to procedure call) assigns a new transaction ID value, regardless of whether you've actually started a transaction. See an example of using this function in the next section (STEP_ID). 4.2.7.2 The DBMS_TRANSACTION.STEP_ID function The STEP_ID function returns the unique positive integer that orders the DML operations of the current transaction. Here's the specification for the function: FUNCTION DBMS_TRANSACTION.STEP_ID RETURN NUMBER; If a transaction has not been initiated, then this function returns NULL. Values of step ID across transactions do not appear to have any guaranteed relationship to each other. Within a transaction, however, they will always be increasing. The following script (written by John Beresniewicz) demonstrates the usage and output of the LOCAL_TRANSACTION_ID and STEP_ID functions: /* Filename on companion disk: transid.sql */* set serveroutput on size 1000000 CREATE TABLE foo (col1 NUMBER); DECLARE trx VARCHAR2(200); step NUMBER; PROCEDURE printem(message_IN IN VARCHAR2) IS BEGIN DBMS_OUTPUT.PUT_LINE(message_IN); DBMS_OUTPUT.PUT_LINE ('Trx id: '||RPAD(NVL(trx,'NULL'),30)|| 'Step: '||NVL(TO_CHAR(step),'NULL') ); END printem; PROCEDURE getem IS BEGIN trx := DBMS_TRANSACTION.local_transaction_id; step := DBMS_TRANSACTION.step_id; END getem; BEGIN /* close any open transaction */ COMMIT; /* how does it look at start of trx? */ getem; printem('BEGIN'); /* || do some DML and see how step changes */ INSERT INTO foo SELECT ROWNUM FROM dictionary; getem; printem('INSERT'); UPDATE foo SET col1 = col1 + 1; getem; printem('UPDATE'); DELETE FROM foo WHERE MOD(col1,2) = 0; getem; printem('DELETE'); /* || now commit, they should be null */ COMMIT; getem; printem('COMMIT'); /* || now explicitly open a new transaction [Appendix A] What's on the Companion Disk? 4.2.7 Returning Transaction Identifiers 232 */ trx := DBMS_TRANSACTION.local_transaction_id(TRUE); getem; printem('NEW TRX FORCED'); END; / The results of this script follow: SQL> @transid.sql Table created. BEGIN Trx id: NULL Step: NULL INSERT Trx id: 1.6.28680 Step: 42802896748631309 UPDATE Trx id: 1.6.28680 Step: 42802896748632625 DELETE Trx id: 1.6.28680 Step: 42802896748633616 COMMIT Trx id: NULL Step: NULL NEW TRX FORCED Trx id: 2.7.28508 Step: 42045333236522790 4.1 DBMS_LOCK: Creating and Managing Resource Locks 5. Oracle Advanced Queuing Copyright (c) 2000 O'Reilly & Associates. All rights reserved. [Appendix A] What's on the Companion Disk? 4.2.7 Returning Transaction Identifiers 233 Chapter 5 234 5. Oracle Advanced Queuing Contents: Oracle AQ Concepts Getting Started with Oracle AQ Oracle AQ Nonprogram Elements DBMS_AQ: Interfacing to Oracle AQ (Oracle8 only) DBMS_AQADM: Performing AQ Administrative Tasks (Oracle8 only) Oracle AQ Database Objects Oracle AQ Examples Oracle8 offers a facility (new to Oracle 8) called Oracle AQ (Oracle Advanced Queuing, referred to as AQ in this chapter) that will make it much easier for developers to build applications that require deferred execution of activity. Oracle is positioning Oracle AQ as an alternative to the queuing mechanisms of teleprocessing monitors and messaging interfaces. Oracle AQ will serve as a foundation technology for workflow management applications, both those delivered by Oracle Corporation itself and those implemented by third parties. From a PL/SQL standpoint, Oracle AQ is made available through two packages: DBMS_AQADM and DBMS_AQ. The DBMS_AQADM package is the interface to the administrative tasks of Oracle AQ. These tasks include: • Creating or dropping queue tables that contain one or more queues • Creating, dropping, and altering queues, which are stored in a queue table • Starting and stopping queues in accepting message creation or consumption Most users of the Oracle AQ facility will not work with DBMS_AQADM. The DBA will most likely initialize all needed queue tables and queues. PL/SQL developers will instead work with the DBMS_AQ, whose tasks include: • Creating a message to the specified queue • Consuming a message from the specified queue Most of the background information presented early in this chapter applies to both packages. Later, we'll provide individual discussions of the two packages and their programs. Oracle AQ is full of features and offers tremendous flexibility in how you manipulate messages in queues. It also has only a handful of programs with which to administer and operate the queues. This relatively small number of procedures and functions can, nevertheless, be misleading. You will probably encounter lots of frustrating moments as you come up to speed on Oracle AQ (I know I did). Some of the frustration will arise from the way that Oracle allows you to modify the characteristics of queues, queue tables, and specific enqueue and dequeue operations by setting individual fields of PL/SQL records, which are then passed to the appropriate programs as arguments. If you are not comfortable with declaring and manipulating record structures in PL/SQL, you should read through Chapter 9 of Oracle PL/SQL Programming (O'Reilly & Associates, 1997) before continuing with this chapter. 5. Oracle Advanced Queuing 235 . Performing AQ Administrative Tasks (Oracle8 only) Oracle AQ Database Objects Oracle AQ Examples Oracle8 offers a facility (new to Oracle 8) called Oracle AQ (Oracle Advanced Queuing, referred to. 233 Chapter 5 234 5. Oracle Advanced Queuing Contents: Oracle AQ Concepts Getting Started with Oracle AQ Oracle AQ Nonprogram Elements DBMS_AQ: Interfacing to Oracle AQ (Oracle8 only) DBMS_AQADM:. deferred execution of activity. Oracle is positioning Oracle AQ as an alternative to the queuing mechanisms of teleprocessing monitors and messaging interfaces. Oracle AQ will serve as a foundation