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

前端 未结 6 968
一个人的身影
一个人的身影 2021-01-02 11:17

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 que

相关标签:
6条回答
  • 2021-01-02 11:43

    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)
    [...]
    0 讨论(0)
  • 2021-01-02 11:49

    TLDR : On select from remote database you also create session and connection for remote DB. That session and connection persists as long as local user session. As you can guess this can lead to some problems with keeping up with session and connections.

    SO ALWAYS DO A COMMIT : SELECT * FROM emp@sales; COMMIT;

    I like a long read section :

    This was bugging me also so much why there is an transaction on selects from db_links and decided to finally end this so from oracle documentation :

    Oracle® Database Administrator's Guide 11g Release 2 (11.2) https://docs.oracle.com/html/E25494_01/ds_appdev002.htm

    Controlling Connections Established by Database Links When a global object name is referenced in a SQL statement or remote procedure call, database links establish a connection to a session in the remote database on behalf of the local user. The remote connection and session are only created if the connection has not already been established previously for the local user session.

    The connections and sessions established to remote databases persist for the duration of the local user's session, unless the application or user explicitly terminates them. Note that when you issue a SELECT statement across a database link, a transaction lock is placed on the undo segments. To rerelease the segment, you must issue a COMMIT or ROLLBACK statement.

    Terminating remote connections established using database links is useful for disconnecting high cost connections that are no longer required by the application. You can terminate a remote connection and session using the ALTER SESSION statement with the CLOSE DATABASE LINK clause. For example, assume you issue the following transactions:

    SELECT * FROM emp@sales; COMMIT; The following statement terminates the session in the remote database pointed to by the sales database link:

    ALTER SESSION CLOSE DATABASE LINK sales; To close a database link connection in your user session, you must have the ALTER SESSION system privilege.

    Note: Before closing a database link, first close all cursors that use the link and then end your current transaction if it uses the link.

    See Also: Oracle Database SQL Language Reference for more information about the ALTER SESSION statement

    0 讨论(0)
  • 2021-01-02 11:54

    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.

    0 讨论(0)
  • 2021-01-02 11:56

    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).

    0 讨论(0)
  • 2021-01-02 11:57

    Select is a part of DML only but lock is not acquired, A row lock is fetched upon insert/update/delete/ select for update. -Ross is right.

    https://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_locks001.htm#SQLRF55502

                            ROW Lock    Table lock
    

    SELECT ... FROM table... ----- None

    INSERT INTO table ... Yes SX

    Same with update delete and select for update.

    0 讨论(0)
  • 2021-01-02 11:59

    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.

    0 讨论(0)
提交回复
热议问题