List current DML in DB including SELECT for Update

In order to list all currently opened DML we can select v$open_cursor and link it to to v$SQL in order to retrieve the v$SQL.COMMAND_TYPE.
All DML operation have the following number in v$sql.command_type :
2 : 'INSERT'
6 : 'UPDATE',
7 : 'DELETE',
189 : 'MERGE'
But 'SELECT for update it is still 3 like any non regular SELECT.
I did not found information in v$lock nor in v$transaction that would allow me
to link an open cursor of type 3 (SELECT but in fact for update) to the opened transaction in v$transaction.
Does anybody knows how to assert than a SELECT is in fact a DML short of grepping the 'FOR update' in the SQL text.
Such an Horrible trick would force me to search all opened cursor text for each session with an entry in v$transaction.

Thanks for replying.
I could have had the usage of less aggressivity and more competences. You advice is simply stupid :
-- seesion 1 :
select * from toto where id = 20 for update ;
select sid from v$mystat where rownum = 1 ;   -- > sid=1614
-- session control : check v$transaction
col version new_value version noprint
col field new_value field noprint
col used_urec format 999999 head 'Undo|Records'
col undo_size head 'Undo|size (k)' justify c
set lines 150
select substr(version,1,instr(version,'.',1)-1) version from v$instance;
select decode(&version,9,'','XID,') field from dual;
Select r.segment_name,To_Char(To_Date(vt.Start_Time,'MM-DD-RR HH24:MI:SS'),'MM-DD HH24:MI:SS') strt
     ,  decode(vs.status,'ACTIVE',vs.last_Call_et,0) since , vs.sid, vs.status se_status,
       &field vt.status tr_status, log_io, phy_io,cr_get,cr_change, vt.used_urec, vt.used_ublk * p.value/1024 undo_size
  From dba_rollback_segs dr,
       v$rollstat rs,
       v$transaction vt,
       v$session vs,
       v$process vp,
       dba_rollback_segs r,
       v$parameter p
  Where vs.Paddr = vp.Addr (+) AND p.name  = 'db_block_size'
   and vt.xidusn (+)  = r.segment_id
   And vs.UserName Is Not Null
   And vs.Taddr Is Not Null
   And vs.Taddr = vt.Addr
   And vt.xidusn = dr.segment_id
   And vt.xidusn = rs.usn
    Order By VS.OsUser, To_Date(vt.Start_Time,'MM-DD-RR HH24:MI:SS') ;
                               Running        Session                   Transact                                                Undo    Undo
SEGMENT_NAME Start time       time (s)    SID Status   XID              Status       LOG_IO     PHY_IO     CR_GET  CR_CHANGE Records  size (k)
_SYSSMU21$   04-13 11:02:24          0   1614 INACTIVE 0015002A0003A800 ACTIVE            3          0        104          0       1          8
-- so we have a transaction in 1614. Let's retrieve its SQL :
-- session control : what do we have in  v$session :
  1  select sql_hash_value, b.sql_text sql_text, prev_hash_value , bb.sql_text prev_sql_text
  2    from
  3       v$session  a, v$sql b, v$sql bb
  4  where sid = 1614
  5    and a.sql_hash_value = b.hash_value (+)
  6*   and a.prev_hash_value = bb.hash_value (+)
SQL> /
SQL_HASH_VALUE SQL_TEXT                                      PREV_HASH_VALUE PREV_SQL_TEXT
             0                                                     897388722 select sid from v$mystat where rownum = 1
-- gone !
-- Conclusion : joining v$session to v$transaction is useless if you want to retrieve the SQL in system currently opened.
-- moreover, if  start a transaction with many queries, you are still limited to 2 slot in v$session.

Similar Messages

  • When is SELECT FOR UPDATE used

    DB version:10gR2
    Since another thread of mine on this subject didn't go well, i am starting another thread.
    When exactly is SELECT..FOR UPDATE statement used? With the exception of using SELECT...FOR UPDATE in CURSOR declaration, I've rarely seen SELECT ...FOR UPDATE being used explicitlyby PL/SQL gurus in our firm. Why didn't they use SELECT..FOR UPDATE(i mean a stand alone SELECT FOR UPDATE, <em>not as a part of Cursor</em>) to lock rows before UPDATE/DELETE/INSERT in their codes?
    Edited by: M.Everett on Oct 20, 2008 12:00 PM
    edited the initial post to let the users know that I am refering to a stand alone SELECT FOR UPDATE statement, not the part of a cursor

    M.Everett wrote:
    What i gather from various sources in the Internet:
    1. SELECT FOR UPDATE is used mainly on CURSORs and very rarely used as a stand alone statement (if this is not the case you would have seen SELECT FOR UPDATE statements before every UPDATEs and DELETEs in PL/SQL codes)
    2. Stand alone SELECT FOR UPDATEs are used mainly when dealing with CLOB, BLOB
    Am i right in making these conclusions?1. This is probably a fair assumption.
    2. Not really. SELECT FOR UPDATE is not a requirement when dealign with (C|B)LOBs.
    SELECT FOR UPDATE allows an easy form of reference when you come to update rows in a cursor loop (although cursor loops should be rarely used), because rather than having to include a where condition on key columns you can just refer to the CURRENT ROW. Obviously, the main reason for using SFUs is the locking and this can become a requirement in some business environments where a user "picks up" a record to deal with and other users will then not see that record in their list or be able to select it for themselves.
    ;)

  • I accidently deleted the playlist selected for updating thing...

    i was adding new songs to my ipod and i guess there were too many songs there so it asked me if i wanted it to choose some songs randomly...
    so i chose "ok" but actually i didnt really want it to choose songs on its own so i deleted the list that was automatically created by itself and decided to delete some songs on my own...
    after doin that, i tried to update it but now it says i cant do it because i deleted that list...
    it says "songs on the ipod "stephanie kim" cannot be updated because all of the playlists selected for updating no longer exists"
    i turned my computer off and tried it again several times but it wont work...
    and all the songs in my ipod are gone now...
    is there anything i can do?

    http://support.apple.com/kb/PH10918
    Best.

  • Rogue implicit SELECT FOR UPDATE statement in forms 9i  9.0.4.0.19

    all,
    out of 200 production forms, one form occasionally and incorrectly "selects for update" an entire 3 million row table, during an update transaction. this creates 100+ archive logs.
    we cannot repeat the event via testing. but the rogue select statement has been captured from SGA and is listed below. its plain to see that somehow the where clause is truncated to a W, and is then used as a table alias, resulting in the entire table being locked.
    has anyone seen anything like this?
    SELECT ROWID,DISTRIBUTION_PARTY,DISTRIBUTION_PARTY_NAME,CORRESPOND_SEQ_NUM,DISTRIBUTION_SEQ_NUM,VENDOR_NUM,DEPENDENT_SEQ_NUM,INTERNAL_ATTORNEY_USER_NAME,MAIL_LOC,ORIGINAL_FLAG
    FROM CLAIM_DISTRIBUTION_DATA W
    FOR UPDATE OF DISTRIBUTION_PARTY NOWAIT

    Find out where this select statement is issued from first of all. Is it in your code or is it issued implicitely by Forms? Since it has rowid I assume it is an implicit Forms call.
    Do you use on-update triggers any where in this form? on-lock?

  • Deadlock detected during SELECT FOR UPDATE - an application error?

    I have a general question about how Oracle prevents deadlocks from affecting
    applications: do I need to build support into the application for handling
    deadlocks when they occur in this particular scenario, or should Oracle handle
    this for me? I'd like to know whether this is "normal" behavior for an Oracle
    application, or if there is an underlying problem. Consider the following situation:
    Two sessions issue individual SELECT FOR UPDATE queries. Each query locates
    records in the table using a different index. These indexes point to rows in a
    different order from each other, meaning that a deadlock will occur if the two
    statement execute simultaneously.
    For illustrative purposes, consider these rows in a hypothetical table.
    ALPHABET
    alpha
    bravo
    charlie
    delta
    echo
    foxtrot
    golf
    hotel
    Index A results in traversing the table in ascending alphabetical order; index
    B, descending. If two SELECT FOR UPDATE statements concurrently execute on this
    table--one with an ascending order execution path and one in descending order--
    the two processes will deadlock at the point where they meet. If Session A
    locks alpha, bravo, charlie, and delta, while Session B locks hotel, golf,
    foxtrot, and echo, then neither process can proceed. A needs to lock echo, and
    B needs to lock delta, but one cannot continue until the other releases its
    locks.
    This execution path can be encouraged using hints. Executing queries similar to these on larger tables will generate the "collision" as described above.
    -- Session A
    select /*+ index_asc (customer) */
    from customer
    where gender = 'M'
    for update;
    -- Session B
    select /*+ index_desc (customer) */
    from customer
    where gender = 'M'
    for update;
    Oracle will recognize that both sessions are in a stand-off, and it will roll
    back the work performed by one of the two sessions to break the deadlock.
    My question pivots on whether or not, in this situation, the deadlock gets
    reported back to the application executing the queries as an ORA-00060. If
    these are the ONLY queries executed during these sessions, I would think that
    Oracle would rollback the locking performed in one of the SELECT FOR UPDATE
    statements. If I understand correctly,
    (1) Oracle silently rolls back and replays work performed by UPDATE statements
    when a deadlock situation occurs within the scope of the update statement,
    and
    (2) A SELECT FOR UPDATE statement causes Oracle, at the point in time the cursor
    is opened, to lock all rows matching the WHERE clause.
    If this is the case, then should I expect Oracle to produce an ORA-00060
    deadlock detection error for two SELECT FOR UPDATE statements?
    I would think that, for deadlock situations completely within Oracle's control,
    this should be perceived to the application invoking the SELECT FOR UPDATE
    statements as regular blocking. Since the query execution plans are the sole
    reason for this deadlock situation, I think that Oracle would handle the
    situation gracefully (like it does for UPDATE, as referenced in (1)).
    Notice, from the trace file below, that the waits appear to be from row locking,
    and not from an artificial deadlock (e.g. ITL contention).
    Oracle8i Enterprise Edition Release 8.1.7.4.0 - 64bit Production
    With the Partitioning option
    DEADLOCK DETECTED
    Current SQL statement for this session:
    SELECT XXX FROM YYY WHERE ZZZ LIKE 'AAA%' FOR UPDATE
    ----- PL/SQL Call Stack -----
    object line object
    handle number name
    58a1f8f18 4 anonymous block
    58a1f8f18 11 anonymous block
    The following deadlock is not an ORACLE error. It is a
    deadlock due to user error in the design of an application
    or from issuing incorrect ad-hoc SQL. The following
    information may aid in determining the deadlock:
    Deadlock graph:
    ---------Blocker(s)-------- ---------Waiter(s)---------
    Resource Name process session holds waits process session holds waits
    TX-002f004b-000412cf 37 26 X 26 44 X
    TX-002e0044-000638b7 26 44 X 37 26 X
    session 26: DID 0001-0025-00000002     session 44: DID 0001-001A-00000002
    session 44: DID 0001-001A-00000002     session 26: DID 0001-0025-00000002
    Rows waited on:
    Session 44: obj - rowid = 0000CE31 - AAANCFAApAAAAGBAAX
    Session 26: obj - rowid = 0000CE33 - AAANCHAArAAAAOmAAM
    Thanks for your insight,
    - Curtis
    (1) "Oracle will silently roll back your update and restart it"
    http://tkyte.blogspot.com/2005/08/something-different-part-i-of-iii.html
    (2) "All rows are locked when you open the cursor, not as they are fetched."
    http://download-east.oracle.com/docs/cd/A87860_01/doc/appdev.817/a77069/05_ora.htm#2170
    Message was edited by:
    Curtis Light

    Thanks for your response. In my example, I used the indexes to force a pair of query execution plans to "collide" somewhere in the table in question by having one query traverse the table via index in an ascending order, and another in descending. This is an artificial scenario for reproducible illustrative purposes, but similar collisions could legitimately occur in real world scenarios (e.g. a full table scan and an index range scan with lookup by ROWID).
    So, with that said, I think it would be unreasonable for Oracle to report the collision as a ORA-00060 every time it occurs because:
    (1) The UPDATE statement handles this situation automatically, and
    (2) An ORA-00060 results in a 100+KB trace file being written out, only rational for truly erroneous situations.
    I agree that, when the application misbehaves and locks rows out of order in separate SQL statements, then Oracle should raise an ORA-00060, as the deadlock is outside of its control. But in this case, the problem occurs with just two individual SQL statements, each within its own transaction.

  • JDBC SELECT FOR UPDATE

    I'm trying to issue a SELECT ... FROM ... FOR UPDATE, and under specific verified conditions runs an UPDATE (where the current is positioned!).
    The error code I get is:
    ORA-01002: Fetch out of sequence.
    Here you are my code:
    /////////////////////START
    import java.sql.*;
    import oracle.jdbc.*;
    import oracle.sql.*;
    public class SelForUpdDin{
    static{
         try{
              Class.forName("oracle.jdbc.driver.OracleDriver");
         catch(Exception e){e.printStackTrace();}
    // Queries and cursor name
    public static void main (java.lang.String[] args){
    String cursorName = null;
    int codice = 0;
    String cognome = null;
    String job = null;
    int manager = 0;
    java.sql.Date dataAss = null;
    int salario = 0;
    int commissioni = 0;
    int reparto = 0;
    String rowid = null;
    String sqlSelect = "SELECT empno, ename, "+
    "job, mgr, hiredate, sal, comm, deptno, ROWID "+
    "FROM scott.emp FOR UPDATE";
    String sqlUpdate = "UPDATE scott.emp SET comm = ? WHERE ROWID = ? ";
    try {
    Connection con = DriverManager.getConnection("jdbc:Oracle:oci8:@","system","manager");
    // Esecuzione della SELECT e produzione del RESULT SET
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(sqlSelect);
    PreparedStatement ps = con.prepareStatement(sqlUpdate);
    while (rs.next()) {
    codice = rs.getInt(1);
    cognome = rs.getString(2);
    job = rs.getString(3);
    manager = rs.getInt(4);
    dataAss = rs.getDate(5);
    salario = rs.getInt(6);
    commissioni = rs.getInt(7);
    reparto = rs.getInt(8);
    rowid = rs.getString(9);
    // Applicazione della business logic
    if (reparto == 30)
    { System.out.println (cognome + " in dept= "+ reparto +
    " with salary=" + salario + " has a commission= " +
    commissioni);
    int newcomm = 5555;
    ps.setInt(1,newcomm);
    ps.setString(2,rowid);
    ps.executeUpdate();
    else
    { System.out.println (cognome + " in dept= "+ reparto +
    " with salary=" + salario + " has a commission= " + commissioni);
    } // if - else
    } // end while
    rs.close();
    ps.close();
    stmt.close();
    catch(Exception e)
    e.printStackTrace();
    } // end main()
    } // end class
    //PS.
    //Many thanks to Bachar and Elangovan that ansewerd me to my previous posting and addressed me towards the right solution

    Hi
    The documentation gives following explanation for the error :
    ORA-01002 fetch out of sequence
    Cause: In a host language program, a FETCH call was issued out of sequence. A successful parse-and-execute call must be issued before a fetch. This can occur if an attempt was made to FETCH from an active set after all records have been fetched. This may be caused by fetching from a SELECT FOR UPDATE cursor after a commit. A PL/SQL cursor loop implicitly does fetches and may also cause this error.
    Action: Parse and execute a SQL statement before attempting to fetch the data.
    In your program you should set auto commit to false as follows :
    con.setAutoCommit(false);
    Do this before executing the SELECT FOR UPDATE sql query.
    At the end of program you can commit to save the updations as follows:
    con.commit();
    This should solve the problem.
    Chandar

  • Audit "SELECT FOR UPDATE" statement

    Hi all
    My database is 10.2.0.3 and I enabled audit_trail to DB value already.
    My purpose I want to audit "SELECT FOR UPDATE" statement on the table and I tried to enable audit "SELECT" on the table that have many records in dba_audit_trail because "SELECT" statement that include in this audit and then I tried to enable audit "LOCK TABLE" on the table that doesn't have any records n dba_audit_trail.
    So my question is How to enable audit for collecting only "SELECT FOR UPDATE" statement? or anyone have any idea for this.
    Regards,
    Hiko

    taohiko wrote:
    Hi all
    My database is 10.2.0.3 and I enabled audit_trail to DB value already.
    My purpose I want to audit "SELECT FOR UPDATE" statement on the table and I tried to enable audit "SELECT" on the table that have many records in dba_audit_trail because "SELECT" statement that include in this audit and then I tried to enable audit "LOCK TABLE" on the table that doesn't have any records n dba_audit_trail.
    So my question is How to enable audit for collecting only "SELECT FOR UPDATE" statement? or anyone have any idea for this.
    A consideration on top of the comments made by Justin:
    You have an unfortunate version of the database for auditing: when you enable audit on 10.2.0.3 (or.2 or .1) the redo pattern changes - normally you will see a redo change vector for each row updated, but in these versions you will see two records, a "lock row" followed up "update row piece"; which means your volume of redo may increase significantly.
    I wrote a note about it some time ago: http://jonathanlewis.wordpress.com/2011/05/27/audit-ouch/ and one of the comments includes the bug number ( 5166745 ), reporting fixed in 10.2.0.4 and 11.1.0.6
    Regards
    Jonathan Lewis
    This is bug

  • Oracle select for update: not releasing lock

    My JDBC code uses "select for update" to modify record in Oracle database. I tried to simulate network connection down situation.
    After my JDBC code locked on a record using "select for update", I unplugged the network cable. I then tried to run the same code on another computer, but it could not accquire the lock, because the previous lock was not released. I tried sqlplus to lock the record, but failed also. The lock has been there for at least an hour now. I guess it may finally be released, but is there a way for oracle to release the lock as soon as the connection is down? Not know if it is a JDBC setting or oracle setting.

    Dear Friend,
    What you are trying to do is not correct way of checking the concurrency and transaction.
    The reason is as listed below.
    01.Always remember http is a stateless protocol and removing the connection or just closing the browser will never be informed to the database or to the application server thus the transaction monitor (TM)or processor will never release the lock as it will deem that the actor is manipulating the data.
    02.As per locking goes every database is having a �TM� and the default isolation level setting is different like oracle uses serializable DB2udb 7.0 or db2/As400 uses repeatable read. You can change this setting by editing the default setting in the database but be very sure before touching it.
    03.     You can also transpose this with your Application server setting for that piece of code or Globally but again be very sure about it as it will change the entire gamete.
    04.     For releasing lock you have to manually do it or you can change the settings of App server or the Database to release the connection after some wait time.
    Regards,
    Ruchir

  • Database select for update locks ADF

    Hi,
    When a user has initiated an update session in an adf application and locking is optimistic it will acquire a lock on table row using select for update no wait; . But when the user closes a tab the session would not be terminated. Now i know as HTTP is a stateless protocol, we can wait for the timeout and then the lock will be released using a session listener implementation. But if the user instead tries to log in again in a new tab and tries to edit the same record he will receive a message stating that another user already holds a lock on the record which is correct, but is misleading.
    So can we rely on javascript for these scenarios that as soon as the user closes the tab the session should be terminated.
    Here's a snippet
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.4/dojo/dojo.xd.js" ></script>
    <script type="text/javascript">
    var unLoad = function() {
        dojo.io.script.get({
        url:'http://127.0.0.1:7101/myapp/adfAuthentication?logout=true',
        timeout:15000,
      dojo.addOnWindowUnload(unLoad);
    </script>I know this might not work always as it depends on the fact that request might / might not be processed by the server.
    Are there any alternate solutions and also reducing the session timeout is ruled out in my scenario.

    Ramandeep,
    So are there other alternatives or solutionsAlternatives or solutions to what, exactly? As Jobinesh has told you, as long as you use optimistic locking, ADF doesn't acquire database locks except in the context of a transaction that is going to be completed in the current HTTP request. You could obviously force ADF to deviate from this if you called "postChanges" during an HTTP request and leave the transaction hanging, but that would just be wrong in an optimistic locking scenario - the solution would be "don't do that."
    John

  • SELECT FOR UPDATE - does it write to REDO?

    Greetings folks,
    we have some strange performance issues with a recent application update. This is custom in-house application. Every morning since the deploy we get a spike in load, especially to log sync / redo archive. We capture activity surrounding the load, and found many "select for update" statements.
    Im digging through metalink and docs looking to confirm "write or no write" to the redo log files. comments appreciated.

    sb92075 wrote:
    SELECT does not generate REDO
    DML generates REDO.It is possible for a SELECT to generate redo due to the effects of delayed block cleanout. A small test case:
    Session 1:
    CREATE TABLE T10 AS
    SELECT
      ROWNUM RN
    FROM
      DUAL
    CONNECT BY
      LEVEL<=1000;
    UPDATE
      T10
    SET
      RN=RN;
    UPDATE
      T10
    SET
      RN=RN;
    UPDATE
      T10
    SET
      RN=RN;
    Session 2:
    ALTER SYSTEM FLUSH BUFFER_CACHE;
    ALTER SYSTEM FLUSH BUFFER_CACHE;
    Session 1:
    COMMIT;
    Session 2:
    SET AUTOTRACE ON STATISTICS
    SELECT
    FROM
      T10;
    1000 rows selected.
    Statistics
              0  recursive calls
              0  db block gets
             73  consistent gets
              3  physical reads
            188  redo size
          11104  bytes sent via SQL*Net to client
           1060  bytes received via SQL*Net from client
             68  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
           1000  rows processedNote that the above may be performed in a single session rather than using two sessions. Essentially, the flush of the buffer cache causes the dirty blocks (containing uncommitted changes) to be written to disk, and the blocks are "cleaned up" during the next SELECT which accesses the blocks.
    A much better explanation:
    http://jonathanlewis.wordpress.com/2009/06/16/clean-it-up/
    Charles Hooper
    IT Manager/Oracle DBA
    K&M Machine-Fabricating, Inc.

  • Updatable View issues:  cannot select FOR UPDATE from view with DI

    Hi All,
    I have a simple view XY and an instead of trigger on that to insert data into one table which is used in the my view. When I do insert statement on view XY it is working fine from sql but when i used same thing with page process of " Process Row of XY Automatic Row Processing (DML) " i am getting following error. I am using APEX 3.0 . Please help me.
    ORA-20001: Error in DML: p_rowid=xxxx, p_alt_rowid=abc, p_rowid2=, p_alt_rowid2=. ORA-02014: cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc.
    Thanks

    James,
    are you already on 3.0.1.00.07 or 3.0.1.00.08? Have a look at the release notes, it says something about a bug fix for some occurrences of ORA-02014.
    Also have a look at the new substitution value/item FSP_DML_LOCK_ROW which turns locking off if you set it to FALSE. See http://www.oracle.com/technology/products/database/application_express/html/3.0.1_readme.html#CHDIDIAF and also http://download-west.oracle.com/docs/cd/B32472_01/doc/appdev.300/b32471/advnc.htm#BCGFDAIJ
    Patrick
    My APEX Blog: http://inside-apex.blogspot.com
    The ApexLib Framework: http://apexlib.sourceforge.net
    The APEX Builder Plugin: http://apexplugin.sourceforge.net/ New!

  • Select for update on stateless connections

    i have read that using select for update for a web application will not work specially if the stateless connection are used , and the best way to make sure that the column you are reading was not changed is to use the time stamp approach and not select for update?? i am right

    Not entirely correct.
    A connection/session to Oracle has state. There is no such thing as a stateless Oracle connection.
    The stateless connection is from the web browser to the web server. It makes a connection. Asks for a page (GET, PUT or POST typically). It gets a response from the web server. It closes that connection.
    When the web server response, it opens a (stateful) connection to Oracle. Or it re-uses an existing (stateful) Oracle connection (now idle after having serviced another web browser/web server request).
    The problem with pessimistic locking (e.g. SELECT FOR UPDATE) is that the very same (stateful) Oracle session will either
    a) be closed when a response is send to the web browser
    b) be used for another totally different web browser
    Thus any locks made will either be lost (option a) or will get used by the wrong web browser (option b).
    A method is therefore needed to make the lock spans different Oracle (stateful) sessions. Web browser selects rows to update using Oracle session 101 at Time 1. Web browser submits updated rows and a commit using Oracle session 142 at Time 2.
    The "best way" to handle optimistic locking is likely using the Oracle System Change Number (SCN). This represents the "current version" of the rows.
    So at Time 1, via Session 101, you give the web browser a 100 rows to update - together with the SCN that says the current version of the rows are v1.2.0.1.
    At Time 2, using Session 142, the web browser submits its changes for those 100 rows. Together with the SCN v1.2.0.1.
    The SQL UPDATE issues the update statement - but adds the SCN version criteria. If the UPDATE fails to update all 100 rows, it means that some of the rows no longer exist, or that some rows have a new version number (was changed in the meantime).
    In this case, the UPDATE is rolled back and an exception raised to tell the web browser that some (or all) of those 100 rows have been changed in the meantime.
    Refer to the [url http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/pseudocolumns007.htm#BABFAFIC]Oracle® Database SQL Reference for details.

  • Select for update gives wrong results. Is it a bug?

    Hi,
    Select for update gives wrong results. Is it a bug?
    CREATE TABLE TaxIds
    TaxId NUMBER(6) NOT NULL,
    LocationId NUMBER(3) NOT NULL,
    Status NUMBER(1)
    PARTITION BY LIST (LocationId)
    PARTITION P111 VALUES (111),
    PARTITION P222 VALUES (222),
    PARTITION P333 VALUES (333)
    ALTER TABLE TaxIds ADD ( CONSTRAINT PK_TaxIds PRIMARY KEY (TaxId));
    CREATE INDEX NI_TaxIdsStatus ON TaxIds ( NVL(Status,0) ) LOCAL;
    Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100101, 111, NULL);
    Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100102, 111, NULL);
    Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100103, 111, NULL);
    Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100104, 111, NULL);
    Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (200101, 222, NULL);
    Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (200102, 222, NULL);
    Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (200103, 222, NULL);
    --Session_1 return TAXID=100101
    select TAXID from TAXIDS where LOCATIONID=111 and NVL(STATUS,0)=0 AND rownum=1 for update
    --Session_2 waits commit
    select TAXID from TAXIDS where LOCATIONID=111 and NVL(STATUS,0)=0 AND rownum=1 for update
    --Session_1
    update TAXIDS set STATUS=1 Where TaxId=100101;
    commit;
    --Session_2 return 100101 opps!?
    --Session_1 return TAXID=100102
    select TAXID, STATUS from TAXIDS where LOCATIONID=111 and NVL(STATUS,0)=0 AND rownum=1 for update
    --Session_2 waits commit
    select TAXID, STATUS from TAXIDS where LOCATIONID=111 and NVL(STATUS,0)=0 AND rownum=1 for update
    --Session_1
    update TAXIDS set STATUS=1 Where TaxId=100102;
    commit;
    --Session_2 return 100103                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               

    This is a bug. Got to be a bug.
    This should be nothing to do with indeterminate results from ROWNUM, and nothing to do with read consistency at the point of statement start time in session2., surely.
    Session 2 should never return 100101 once the lock from session 1 is released.
    The SELECT FOR UPDATE should restart and 100101 should not be selected as it does not meet the criteria of the select.
    A statement restart should ensure this.
    A number of demos highlight this.
    Firstly, recall the original observation in the original test case.
    Setup
    SQL> DROP TABLE taxids;
    Table dropped.
    SQL> 
    SQL> CREATE TABLE TaxIds
      2  (TaxId NUMBER(6) NOT NULL,
      3   LocationId NUMBER(3) NOT NULL,
      4   Status NUMBER(1))
      5  PARTITION BY LIST (LocationId)
      6  (PARTITION P111 VALUES (111),
      7   PARTITION P222 VALUES (222),
      8   PARTITION P333 VALUES (333));
    Table created.
    SQL>
    SQL> ALTER TABLE TaxIds ADD ( CONSTRAINT PK_TaxIds PRIMARY KEY (TaxId));
    Table altered.
    SQL>
    SQL> CREATE INDEX NI_TaxIdsStatus ON TaxIds ( NVL(Status,0) ) LOCAL;
    Index created.
    SQL>
    SQL>
    SQL> Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100101, 111, NULL);
    1 row created.
    SQL> Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100102, 111, NULL);
    1 row created.
    SQL> Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100103, 111, NULL);
    1 row created.
    SQL> Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (100104, 111, NULL);
    1 row created.
    SQL> Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (200101, 222, NULL);
    1 row created.
    SQL> Insert into TAXIDS (TAXID, LOCATIONID, STATUS) Values (200102, 222, NULL);
    1 row created.
    SQL> commit;
    Commit complete.
    SQL> Original observation:
    Session1>SELECT taxid
      2  FROM   taxids
      3  WHERE  locationid    = 111
      4  AND    NVL(STATUS,0) = 0
      5  AND    ROWNUM        = 1
      6  FOR UPDATE;
         TAXID
        100101
    Session1>
    --> Session 2 with same statement hangs until
    Session1>BEGIN
      2   UPDATE taxids SET status=1 WHERE taxid=100101;
      3   COMMIT;
      4  END;
      5  /
    PL/SQL procedure successfully completed.
    Session1>
    --> At which point, Session 2 returns
    Session2>SELECT taxid
      2  FROM   taxids
      3  WHERE  locationid    = 111
      4  AND    NVL(STATUS,0) = 0
      5  AND    ROWNUM        = 1
      6  FOR UPDATE;
         TAXID
        100101
    Session2>There's no way that session 2 should have returned 100101. That is the point of FOR UPDATE. It completely reintroduces the lost UPDATE scenario.
    Secondly, what happens if we drop the index.
    Let's reset the data and drop the index:
    Session1>UPDATE taxids SET status=0 where taxid=100101;
    1 row updated.
    Session1>commit;
    Commit complete.
    Session1>drop index NI_TaxIdsStatus;
    Index dropped.
    Session1>Then try again:
    Session1>SELECT taxid
      2  FROM   taxids
      3  WHERE  locationid    = 111
      4  AND    NVL(STATUS,0) = 0
      5  AND    ROWNUM        = 1
      6  FOR UPDATE;
         TAXID
        100101
    Session1>
    --> Session 2 hangs again until
    Session1>BEGIN
      2   UPDATE taxids SET status=1 WHERE taxid=100101;
      3   COMMIT;
      4  END;
      5  /
    PL/SQL procedure successfully completed.
    Session1>
    --> At which point in session 2:
    Session2>SELECT taxid
      2  FROM   taxids
      3  WHERE  locationid    = 111
      4  AND    NVL(STATUS,0) = 0
      5  AND    ROWNUM        = 1
      6  FOR UPDATE;
         TAXID
        100102
    Session2>Proves nothing, Non-deterministic ROWNUM you say.
    Then let's reset, recreate the index and explicity ask then for row 100101.
    It should give the same result as the ROWNUM query without any doubts over the ROWNUM, etc.
    If the original behaviour was correct, session 2 should also be able to get 100101:
    Session1>SELECT taxid
      2  FROM   taxids
      3  WHERE  locationid    = 111
      4  AND    NVL(STATUS,0) = 0
      5  AND    taxid         = 100101
      6  FOR UPDATE;
         TAXID
        100101
    Session1>
    --> same statement hangs in session 2 until
    Session1>BEGIN
      2   UPDATE taxids SET status=1 WHERE taxid=100101;
      3   COMMIT;
      4  END;
      5  /
    PL/SQL procedure successfully completed.
    Session1>
    --> so session 2 stops being blocked and:
    Session2>SELECT taxid
      2  FROM   taxids
      3  WHERE  locationid    = 111
      4  AND    NVL(STATUS,0) = 0
      5  AND    taxid         = 100101
      6  FOR UPDATE;
    no rows selected
    Session2>Of course, this is how it should happen, surely?
    Just to double check, let's reintroduce ROWNUM but force the order by to show it's not about read consistency at the start of the statement - restart should prevent it.
    (reset, then)
    Session1> select t.taxid
      2   from
      3    (select taxid, rowid rd
      4      from   taxids
      5      where  locationid = 111
      6      and    nvl(status,0) = 0
      7      order by taxid) x
      8   ,  taxids t
      9   where t.rowid = x.rd
    10   and   rownum = 1
    11   for update of t.status;
         TAXID
        100101
    Session1>
    --> Yes, session 2 hangs until...
    Session1>BEGIN
      2   UPDATE taxids SET status=1 WHERE taxid=100101;
      3   COMMIT;
      4  END;
      5  /
    PL/SQL procedure successfully completed.
    Session1>
    --> and then
    Session2> select t.taxid
      2   from
      3    (select taxid, rowid rd
      4      from   taxids
      5      where  locationid = 111
      6      and    nvl(status,0) = 0
      7      order by taxid) x
      8   ,  taxids t
      9   where t.rowid = x.rd
    10   and   rownum = 1
    11   for update of t.status;
         TAXID
        100102
    Session2>Session 2 should never be allowed to get 100101 once the lock is released.
    This is a bug.
    The worrying thing is that I can reproduce in 9.2.0.8 and 11.2.0.2.

  • Is SELECT FOR UPDATE lock ever released?

    Hi,
    Does any one know whether the lock acquired by SELECT FOR UPDATE will ever be released if user session ends without commit or rollback(e.g. crashed)? If it does, is there a default parameter to control the maximum wait time for Oracle to release the lock automatically?
    Thanks,
    JM

    Your select statement won't be committed if the db crashes. That is a DML (data manipulation language)statement. In your scenario everything is rolled back upto the last commit or savepoint. For DDL (data definition Language) for the same situation you would get an implicit commit.
    Hope this helps.

  • Select for update no wait distributed polling strategy

    I have an esb process which currently uses 'logicaldeletepolling strategy'.
    I need to change it to use the 'select for update no wait' distributed polling strategy.
    What steps do I need to perform on the existing process ?

    Hi,
    Try: http://download-east.oracle.com/docs/cd/B31017_01/integrate.1013/b28994/adptr_db.htm#sthref558 (Oracle® Application Server Adapters for Files, FTP, Databases, and Enterprise Messaging User's Guide
    10g Release 3 (10.1.3.1.0)
    Part Number B28994-02).
    Also you can reconfigure DB adapter (I think this's the best way): laucnch adapter configuration wizard in JDev and at step 9 (adapter options) check distributed polling checkbox (query now contains for update clause).

Maybe you are looking for