Why do I get an open transaction when just selecting from a database View?

11,993

Solution 1

Any SQL Statement starts a transaction in Oracle.

From the manual:

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. [...] An executable SQL statement is a SQL statement that generates calls to an instance, including DML and DDL statements

Most probably those who are not seing this are running in auto-commit mode where the transaction started by a statement is immediately committed after the statement has finished.

Others have claimed that a SELECT is not DML, but again the manual clearly states:

Data manipulation language (DML) statements query or manipulate data in existing schema objects. They enable you to:

   * Retrieve or fetch data from one or more tables or views (SELECT)
   * Add new rows of data into a table or view (INSERT)
[...]

Solution 2

Contrary to your expectation, it looks like the database link is the source of the open transaction. I've noticed behaviour like this before when running SELECT queries on remote tables in PL/SQL Developer.

To quote Tom Kyte (source):

distributed stuff starts a transaction "just in case".

EDIT: 'Any SQL statement starts a transaction in Oracle'? No, it does not, and here's a demonstration of it. This demonstration uses the data dictionary view V$TRANSACTION, which lists the active transactions. This is all running on my local Oracle XE database, which has no users other than me connected to it.

We'll use the following table during this demonstration. It contains only a single column:

SQL> desc test;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 A                                                  NUMBER(38)

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

No active transactions at the moment. Let's run a SQL query against this table:

SQL> select * from test;

         A
----------
         2

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

Still no active transactions. Now let's do something that will start a transaction:

SQL> insert into test values (1);

1 row created.

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         1

As expected, we now have an active transaction.

SQL> commit;

Commit complete.

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

After committing the transaction, it's no longer active.

Now, let's create a database link. I'm using Oracle XE, and the following creates a database link from my Oracle XE instance back to itself:

SQL> create database link loopback_xe connect to user identified by password using 'XE';

Database link created.

Now let's see what happens when we select from the table over the database link:

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         0

SQL> select * from test@loopback_xe;

         A
----------
         2
         1

SQL> select count(*) from v$transaction;

  COUNT(1)
----------
         1

As you can see, simply selecting from a remote table opens a transaction.

I'm not sure exactly what there is to commit or rollback here, but I have to admit to not knowing the ins and outs of distributed transactions, within which the answer probably lies.

Solution 3

You absolutely cannot open a transaction strictly with a normal query. You may open one across a database link. The guy who posted a link to the doctors either deliberately or utterly carelessly left out the 2nd sentence.

"A transaction in Oracle Database begins when the first executable SQL statement is encountered. An executable SQL statement is a SQL statement that generates calls to an instance, including DML and DDL statements."

SELECT is neither a DML nor a DDL. It is also TRIVIAL to actually test this. I don't want to come off like a troll here, but its really annoying when people just throw out answers on a forum to try to get points and the answers are complete garbage.

Read the rest of the doc and TEST IT FIRST.

  • login to a session
  • run a select
  • see if you have an open transaction by joining v$Session (for your session) to v$transaction.

If a record comes back, you have a transaction. If not, you don't.

Solution 4

Note, according to the Oracle 11g Admin Guide, if you do a plain old SELECT across a database link you will start a transaction, which needs to be committed (or rolled back).

Share:
11,993
James Wiseman
Author by

James Wiseman

I am a Microsoft certified C# developer working in the UK financial services industry. I started my career building software for a chemical weapons detection system for the British army before moving to Scotland to work in legal software. I now develop C# web-based applications in the pensions and life-assurance industry. I've written code since i was 9 years old, initially on my BBC Micro. I've used C#, jQuery, JavaScript. C++, SQL, VB and am proficient web development. I have presented courses in jQuery and have spoken at a local Techmeetup group on JavaScript static analysis. I run a web page and blog dedicated to discussions of my software development experiences. More recently, a thread of consumer-affairs related articles that I have written has featured in the Independent and Mirror newspapers. My personal blog is at http://www.jameswiseman.com/blog/ Twitter: @jameswiseman76 SOreadytohelp

Updated on July 27, 2022

Comments

  • James Wiseman
    James Wiseman almost 2 years

    If I execute a simple select statement in pl/sql developer against a database table, I get a standard set of results back as I would expect.

    Recently, I pasted a query from a stored procedure that happened to select from a view, and noticed that a transaction was seemingly left open. This was appraent by the rollback and commit options were available in PL/SQL developer.

    A poll of other developers revealed that this seems to affect some but not others, which lead me to suspect PL/SQL Developer settings.

    Why on earth would this be the case? The view itelf has a DBLink to another database, but I wouldn't expect this to have any effect.

    Any thoughts?

  • James Wiseman
    James Wiseman over 13 years
    Thanks. How is the Auto-Commit mode toggled?
  • a_horse_with_no_name
    a_horse_with_no_name over 13 years
    I don't use PL/SQL Developer, so I don't know
  • Luke Woodward
    Luke Woodward over 13 years
    @a_horse_with_no_name: not every SQL statement starts a transaction. See the demonstration in my (updated) answer.
  • a_horse_with_no_name
    a_horse_with_no_name over 13 years
    From the Oracle concepts manual: "A transaction begins with the first executable SQL statement. A transaction ends when it is committed or rolled back". download.oracle.com/docs/cd/B28359_01/server.111/b28318/…
  • a_horse_with_no_name
    a_horse_with_no_name over 13 years
    @Pourquoi: See the Oracle concepts manual: "A transaction begins with the first executable SQL statement. A transaction ends when it is committed or rolled back". Why this is not reflected in V$TRANSACTION I cannot tell. download.oracle.com/docs/cd/B28359_01/server.111/b28318/…
  • Luke Woodward
    Luke Woodward over 13 years
    @a_horse_with_no_name: hmmm.... I think the concepts manual may be a bit ambiguous here. I suspect they don't mean to include SELECT when they say 'SQL statements'. I'd guess PL/SQL Developer uses V$TRANSACTION to detect active transactions, and I don't know any way of detecting active transactions without using this view one way or another, hence my answer. See also freelists.org/post/oracle-l/Does-SELECT-start-a-transaction%‌​2c1 , stackoverflow.com/questions/1299694 and stackoverflow.com/questions/506456/#509032
  • a_horse_with_no_name
    a_horse_with_no_name over 13 years
    @Porquoi: Hmm... Oracle needs to have "some kind" of transaction to be able to support read-consistency. When setting the session to serializable V$TRANSACTION does in fact show an entry for a simple SELECT statement. So maybe the "transaction" for a SELECT in READ COMMITTED mode is so "weak" it is not recorded in V$TRANSACTION
  • Gary Myers
    Gary Myers over 13 years
    I think v$transaction tracks a start SCN. For a SERIALIZABLE transaction this does need to include SELECTs but otherwise it should just need to be the point the transaction may need to rollback to if it ever needs to be fully rolled back. Database links need a commit/rollback to close, so maybe that's why they need a v$transaction entry.
  • Luke Woodward
    Luke Woodward over 13 years
    @a_horse_with_no_name: I don't believe a transaction is necessary for a SELECT in READ COMMITTED mode. To achieve read consistency, Oracle just makes a note of the time it started running the SELECT query and goes back into the undo if it comes across any data newer than this. See asktom.oracle.com/pls/apex/…
  • Jon Heller
    Jon Heller over 13 years
    You're right, but just FYI you need to be careful with querying from v$transaction, at least on XE. Some transactions don't appear in that view. For example, "update a set test = 0 where 1 = 2" does not always create rows in v$transaction, but does show up in dbms_transaction.local_transaction_id().
  • Glenn
    Glenn about 12 years
    @Luke_Woodward A query over a db link within Oracle opens a transaction in order to support 2 phase commits. You can query the DBA_2PC_PENDING table to see the entries on the remote db. When querying over the db link, I don't think the initiator can know what the side effects are on the remote db. You may be querying from a function and that function may have side effects modifying data. My experience (8i timeframe): a failure on the initiating db after the query, but before a commit or rollback, left the transaction open on the remote db, locking the row, failing other jobs. Painful to find.
  • a_horse_with_no_name
    a_horse_with_no_name over 10 years
    "SELECT is neither DML nor DDL". The manual begs to differ: docs.oracle.com/cd/B28359_01/server.111/b28318/… SELECT is clearly categorized as a DML statement there.
  • Ross Bradbury
    Ross Bradbury over 9 years
    Sorry, @a_horse_with_no_name but the 11g documentation does explicitly state in SET TRANSACTION that just executing a regular SELECT (without FOR UPDATE) doesn't start a transaction. And as people are demonstrating - and I just learned the hard way today - that seems like the real behavior.
  • Ludovic Kuty
    Ludovic Kuty about 5 years
    @JonHeller Apparently it will appear in v$transaction after the call to dbms_transaction.local_transaction_id has been made (or another DML statement which is not SELECT) . It is a little bit weird. Cfr. stackoverflow.com/a/17706031/452614
  • Ludovic Kuty
    Ludovic Kuty about 5 years
    IMHO The documentation is self contradictory. It looks like writing that DML statements start a transaction is not correct since SELECT in READ COMMITTED does not start a new transaction but it qualifies as DML.