FOR UPDATE SKIP LOCKED

I've been working with the SELECT ...FOR UPDATE SKIP LOCKED feature and it appears to work great for skipping and locking records that are already locked.
But, I've read that it is "undocumented" and I'm wondering if it should not be used since it is undocumented?
Thanks in advance.

It appears in 11g documentation (http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/statements_10002.htm#SQLRF01702 and search for "SKIP LOCKED").
But in 10g R2 it is indeed missing from docs. I'd check with "documentation" forum or with metalink whether it is undocumented on purpose or by mistake.

Similar Messages

  • 11g FOR UPDATE SKIP LOCKED behavior

    Hello pl/sql experts,
    I am trying to test the new SELECT clause in 11g called FOR UPDATE SKIP LOCKED.
    I don't understand why I am getting the following error.
    Here is a test case:
    DROP TABLE T1 PURGE;
    CREATE TABLE t1 (id NUMBER, name VARCHAR2 (10));
    INSERT INTO t1 VALUES (1, 'a');
    INSERT INTO t1 VALUES (1, 'b');
    INSERT INTO t1 VALUES (2, 'a');
    INSERT INTO t1 VALUES (2, 'b');
    INSERT INTO t1 VALUES (3, 'a');
    INSERT INTO t1 VALUES (3, 'b');
    INSERT INTO t1 VALUES (4, 'a');
    INSERT INTO t1 VALUES (4, 'b');
    INSERT INTO t1 VALUES (5, 'a');
    INSERT INTO t1 VALUES (5, 'b');
    INSERT INTO t1 VALUES (6, 'a');
    INSERT INTO t1 VALUES (6, 'b');
    INSERT INTO t1 VALUES (7, 'a');
    INSERT INTO t1 VALUES (7, 'b');
    INSERT INTO t1 VALUES (8, 'a');
    INSERT INTO t1 VALUES (8, 'b');
    INSERT INTO t1 VALUES (9, 'a');
    INSERT INTO t1 VALUES (9, 'b');
    INSERT INTO t1 VALUES (10, 'a');
    INSERT INTO t1 VALUES (10, 'b');
    COMMIT;
    Now run following anonymous pl/sql block in 2 sessions simultaneously.
    SET SERVEROUTPUT ON
    DECLARE
    CURSOR c (c_id t1.id%TYPE)
    IS
    SELECT ROWID rid, id, name
    FROM t1
    WHERE id = c_id
    FOR UPDATE SKIP LOCKED;
    TYPE t_rowid IS TABLE OF ROWID
    INDEX BY BINARY_INTEGER;
    TYPE t_id IS TABLE OF t1.id%TYPE
    INDEX BY BINARY_INTEGER;
    TYPE t_name IS TABLE OF t1.name%TYPE
    INDEX BY BINARY_INTEGER;
    l_rowid t_rowid;
    l_id t_id;
    l_name t_name;
    BEGIN
    FOR i IN ( SELECT DISTINCT id
    FROM t1
    ORDER BY 1)
    LOOP
    OPEN c (i.id);
    LOOP
    FETCH c
    BULK COLLECT INTO l_rowid, l_id, l_name;
    FOR j IN l_id.FIRST .. l_id.LAST
    LOOP
    DBMS_OUTPUT.put_line (l_id (j) || ' : ' || l_name (j));
    END LOOP;
    DBMS_LOCK.sleep (1);
    EXIT WHEN c%NOTFOUND;
    END LOOP;
    CLOSE c;
    END LOOP;
    ROLLBACK;
    END;
    The first session runs fine and produces following output.
    SQL> /
    1 : a
    1 : b
    2 : a
    2 : b
    3 : a
    3 : b
    4 : a
    4 : b
    5 : a
    5 : b
    6 : a
    6 : b
    7 : a
    7 : b
    8 : a
    8 : b
    9 : a
    9 : b
    10 : a
    10 : b
    PL/SQL procedure successfully completed.
    The second session fails:
    SQL> /
    DECLARE
    ERROR at line 1:
    ORA-06502: PL/SQL: numeric or value error
    ORA-06512: at line 32
    Line 32 is: FOR j IN l_id.FIRST .. l_id.LAST
    I keep getting the error in session 2 while the block is still running in session 1. As soon as the block finishes in session 1, session 2 runs without any error and produces the same output as session 1 did.
    I have 2 questions:
    1. Why am I getting this error?
    2. The documentation on FOR UPDATE SKIP LOCKED says the row locks are acquired when a fetch occurs. Does that also apply to BULK FETCH? So should I expect to have 2 rows locked per iteration of the loop in the example above?
    Thank you.

    Toon,
    Thank you. You are absolutely correct.
    The bulk fetch results in zero rows found when they are locked.
    So I need to change my code as follows:
    FETCH c
    BULK COLLECT INTO l_rowid, l_id, l_name;
    IF (l_id.COUNT > 0)
    THEN
    FOR j IN l_id.FIRST .. l_id.LAST
    LOOP
    DBMS_OUTPUT.put_line (l_id (j) || ' : ' || l_name (j));
    END LOOP;
    DBMS_LOCK.sleep (1);
    END IF;
    I need to check to see if the count is greater than zero, then process, else skip the processing.
    Thank you for figuring that out!

  • When does select for update release locks

    Hello all,
    Does anyone know when Oracle realeases the row locks when a
    select for update is issued?
    Does Oracle realase the row lock at the time when an actual update statement is
    issued for the locked row, or does it wait until a commit statment is executed?
    So for example, can I lock several rows with a select for update clause, and then
    issue update statements as many times as I want on each locked row without
    having to worry about the lock being released until I issue a commit statement.
    Thanks,
    David

    yes.
    The lock is released only when your transaction ends. A transaction can end because of:
    1). Commit.
    2). Rollback.
    3). client disconnects.
    etc. etc...

  • FOR UPDATE...SKIP LOCKED - Is it supported to use in 10.2?

    Hi.
    Is the "SKIP LOCKED" feature in SELECT..FOR UPDATE..SKIP LOCKED supported to use in 10.2.0.3?
    It does exactly what we want to do. The patchsets for 10g also contains bug fixes for this feature.
    I know that it's supported (and documented) for 11g, but we have not upgraded yet.
    Also I'm fully aware of the locking mechanism using this feature (it does not lock when opening a cursor,
    it locks when the rows are fetched).
    Regards
    Krister Lundmark

    Also I'm fully aware of the locking mechanism using this feature (it does not lock when opening a cursor,
    it locks when the rows are fetched).Usual FOR UPDATE statement locks data at the moment of cursor opening - according to the concepts it has to get
    locked consistent snapshot before fetching. SKIP LOCKED differs from usual FOR UPDATE in that it
    tries to lock at the moment of fetch and skips rows already locked by other transactions:
    The first transaction:
    SQL> select ename from emp where ename = 'KING' for update;
    ENAME
    KINGThe second: I wait at the moment of cursor opening, not fetching
    SQL> declare
      2   cursor x is select * from emp for update;
      3  begin
      4   open x;
      5  end;
      6  /Now I lock 'KING' and open FOR UPDATE SKIP LOCKED cursor
    SQL> var rc refcursor
    SQL> exec open :rc for select ename from emp where ename in ('KING','ALLEN') for update skip locked;
    PL/SQL procedure successfully completed.I can lock 'ALLEN' in another transaction - cursor opening didn't lock it:
    SQL> select ename from emp where ename = 'ALLEN' for update;
    ENAME
    ALLENAnd then I fetch cursor I find it's empty - I can't find unlocked rows at the fetch stage:
    SQL> print rc
    no rows selectedRgds.

  • Solution to skip an update of locked record

    9.2
    Suppose there is a program which has to updates a record in the table. Record is currently locked
    Need a solution to skip this update (possibly something like in 5 sec).
    Thaks.
    Solution like update ...where lock_status = 0 - is not good in this case
    Edited by: Bolev on Feb 2, 2009 10:41 PM

    Bolev wrote:
    So go back to the original question
    If there is an update in a program and I want to skip record if it is locked , the only solution is opening a cursor for upodate ?
    Is this only way?Bolev,
    yes, I think so, there is no equivalent option in the normal UPDATE DML command as far as I know. If you intend to change the code, I suggest you consider this recent post from Rob van Wijk where he shows a fundamental difference in the behaviour between the "SELECT FOR UPDATE" and the "SELECT FOR UPDATE SKIP LOCKED":
    http://rwijk.blogspot.com/2009/02/for-update-skip-locked.html
    Note in addition that the SKIP LOCKED option has only been officially documented in 11g, so if you're attempting to use it in pre-11g in production like environment (it's available in previous releases, but not officially documented) you might be out of support in case you encounter issues that you want to take up with Oracle support.
    Regards,
    Randolf
    Oracle related stuff blog:
    http://oracle-randolf.blogspot.com/
    SQLTools++ for Oracle (Open source Oracle GUI for Windows):
    http://www.sqltools-plusplus.org:7676/
    http://sourceforge.net/projects/sqlt-pp/

  • Inconsistent Locking with Select for Update

    Hi,
    I seem to be having some issues in using SELECT FOR UPDATE and was hoping to get some insight from the Oralce Guru's out there.
    I have a J2EE application, running in WebLogic 8.1.4 using Oralce 9.2.0.1.0.
    The application contains code that requires locking to be done on a specific table with multiple transactions (tx) requesting the same lock. Eg:
    Tx 1: Select * from Zone where Zoneid = 'Zone1' for update (Obtains lock)
    Tx 2: Select * from Zone where Zoneid = 'Zone1' for update (waits)
    Tx 100: Select * from Zone where Zoneid = 'Zone1' for update
    Tx1 commits.
    It appears that the following transactions, i.e. Tx2 - Tx100 do not seem to execute in the order the lock was requested. That is Tx 100 always appears to be the second last transaction to execute, after which some arbitrary transaction between Tx2 - Tx99 will execute after Tx100 has committed.
    This seems to tell me that the lock is not being handed in a FIFO manner and is causing us great pain as our data is not longer consistent.
    Does anyone know how i might be able to trace which transaction is being awarded the lock? Also if anyone has any suggestion on how to troubleshoot/solve this issue, greatly appreciated.
    TIA
    Prem

    Oracle does not have a lock queue/manager at all. The locked status of a record is essentially an attribute of the record itself. It is stored on the datablock header. When a transaction requests a lock and can't get it, and is willing to wait (SELECT FOR UPDATE without NOWAIT), it first spins while waiting for the lock (four times as I recall), then sleeps waiting for the lock. The the more times it sleeps before getting the lock, the longer it will sleep before trying again.
    What is likely happening here is that transaction 100 is still spinning when transaction 1 commits, so checks back more frequently and gets the lock first. The rest get the lock whenever they wake up and noone else has taken the lock.
    If you need the transaction to occur in order, then I do not think you can use Oracle's native locking mechanism. Depending on what exactly you are trying to do, you may want to look at Advanced Queueing, or possibly the built-in package DBMS_LOCK.
    HTH
    John

  • RE: for update clause

    Hi,
    If you are using Forte as 2-tier tools, there shouldn't be any problem in
    using select ... for update. The sql is actually passed through to your
    back-end database. So everything should work the same, provided that every
    user has his own database session ( like by using DBResourceMgr to create
    DBSession at run-time for each user. )
    However, if you are building multi-tier application, there is no simple
    answer to your question. The problem is common to all 3-tier application
    since the application / database layer is shared among many users. If you
    start a transaction from client side, use select ... for update to lock a
    record, allow user to change data, then update and end the transaction, you
    are not just locking up a record, but also a database session. In such
    model, you will run out of DBSession very soon.
    What we did here is to use a "lock count", which exists is every table.
    When client retrieves a record, it won't start a transaction there. A
    transaction is started only on the server and after client commits its
    changes to the server. Data consistency is checked by checking the lock
    count in the update where clause.
    It looks dumb, but it's the only solution that we can reach after consulting
    a lot of white paper and Forte consultants. Moreover, Forte consultant also
    said its bad to start a transaction on client side.
    I do hope that there is a better solution out there in handling 3-tier
    applications too. Afterall, this lock count thing is clumsy.
    Peter Sham.
    -----Original Message-----
    From: Phong Tran [SMTP:[email protected]]
    Sent: Thursday, March 18, 1999 6:50 AM
    To: [email protected]
    Subject: for update clause
    dear forte-users,
    I notice the "for update" clause can only used with cursor.
    Just wonder why you can not use it with "sql select ...." statement.
    Also as I understand it, one way to protect the data consistency is
    through
    the mutex lock but then you turn the object to a single-threaded to
    serialize access even though you access different rows in a
    database
    table. The fact is you only want access on a particular row.
    Does anyone know the best way to lock a row (or rows) in the
    database ?
    If you have to rely on the "for update" clause in the cursor
    definition for
    the locking, then you almost end up with a lot of cursors.
    Example: the method ReadnWriteDB(ordeId) accesses a specific row
    but since the orderOBj serializes access, other tasks have to wait.
    OrderObj: OrderMgr = new(IsShared = TRUE, IsTransactional = TRUE);
    method GetOrderInfo() of the TransactionSO.
    begin transaction
    OrderObj.ReadnWriteDB(orderId);
    end transaction;
    From Client:
    Begin
    start task TransactionSO.GetOrderInfo(orderId);
    end;
    Phong
    To unsubscribe, email '[email protected]' with
    'unsubscribe forte-users' as the body of the message.
    Searchable thread archive
    <URL:http://pinehurst.sageit.com/listarchive/>
    To unsubscribe, email '[email protected]' with
    'unsubscribe forte-users' as the body of the message.
    Searchable thread archive <URL:http://pinehurst.sageit.com/listarchive/>

    Which application front end are you using.
    Also, you'll get the same error if your Query runs too long, and/or your rollbacks are too small.

  • Unecessary use of SELECT...FOR UPDATE causing Deadlock

    DB version:10gR2
    We are getting a deadlock issue frequently. When i looked at the trace file i found that the <em>Rolled back SQL</em> and the <em>Successfull SQL</em> are both <strong>SELECT FOR UPDATE</strong> statements. They both are declared before UPDATE statments.
    Both of these PL/SQL codes are developed by a C++ guy. When is it appropriate to use SELECT ..FOR UPDATE. I've seen SELECT ...FOR UPDATE very rarely in the codes developed by PL/SQL gurus in our firm. Why didn't they use SELECT..FOR UPDATE to lock rows before UPDATE/DELETE/INSERT in their codes?

    For update is a rowlevel locking. like
    Session 1
    SQL> conn scott/tiger
    Connected.
    SQL> select * from emp;
         EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
          7369 SMITH      CLERK           7902 17-DEC-80        800                    20
          7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300         30
          7521 WARD       SALESMAN        7698 22-FEB-81       1250        500         30
          7566 JONES      MANAGER         7839 02-APR-81       2975                    20
          7654 MARTIN     SALESMAN        7698 28-SEP-81       1250       1400         30
          7698 BLAKE      MANAGER         7839 01-MAY-81       2850                    30
          7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10
          7788 SCOTT      ANALYST         7566 19-APR-87       3000                    20
          7839 KING       PRESIDENT            17-NOV-81       5000                    10
          7844 TURNER     SALESMAN        7698 08-SEP-81       1500          0         30
          7876 ADAMS      CLERK           7788 23-MAY-87       1100                    20
         EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
          7900 JAMES      CLERK           7698 03-DEC-81        950                    30
          7902 FORD       ANALYST         7566 03-DEC-81       3000                    20
          7934 MILLER     CLERK           7782 23-JAN-82       1300                    10
    14 rows selected.
    SQL> select * from emp where empno = 7369 for update;
         EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
          7369 SMITH      CLERK           7902 17-DEC-80        800                    20
    SQL>
    Session 2
    Connected to:
    Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
    With the Partitioning, OLAP and Data Mining options
    SQL> update emp set sal = 1000 where empno = 7900
      2  /
    1 row updated.
    SQL> commit;
    Commit complete.
    SQL> update emp set sal = 1000 where empno = 7369
      2
    SQL> /In session 1 we have lock row where empno = 7369 & in session 2 we are updating salary where empno = 7900 it is updating successfully, but we are updating a empno = 7369 then session 2nd hangs for waiting for the next session.
    Also read the Link (http://www.oracle.com/technology/oramag/oracle/05-nov/o65asktom.html)

  • Select for update that doesn't return any rows

    Are there any odd side-effects that may occur if a select for update that returns no results is never committed? I wouldn't think there are, but I'm not sure if there would be some kind of overhead or unforeseen consequences. This isn't a terribly important question, but it's come up in some coding I've done and I've not been able to find any documentation addressing it.

    A select for update only locks rows that meet the predicate specified in the where clause. So, if the query returns no rows, no rows are locked.
    session1> SELECT * FROM t;
            ID DESCR
             1 Un
             5 One
             2 THIS IS WA
    session1> SELECT * FROM t
      2  WHERE id = 11 FOR UPDATE;
    no rows selectedA second session can update rows in the table
    session2> UPDATE t
      2  SET descr = 'One'
      3  WHERE id = 1;
    1 row updated.John
    Edited by: John Spencer on Jan 7, 2009 1:36 PM
    I just realized that, although you can do updates on the table after the select fo update that returns no rows, you cannot do DDL operations liike a truncate. Unless the session that does the select for update either ends the transaction (i.e. commit or rollback) or ends the session DDL operations will fail.

  • FOR UPDATE OF how does it work?

    Hi,
    I was wondering what was happening in the databse when a SELECT...FOR UPDATE... is executed. How does Oracle handle this Row Share Table Locks? How does the DB know which rows are locked?
    Thanks for any feedback
    Maurice

    When you do a SELECT ... FOR UPDATE, Oracle locks each row that is returned by the SELECT. The mechanics of locking in Oracle is that the lock bit is actually stored in the row, rather than being centralized in the v$lock table. This allows Oracle to be very scalable and prevents you from worrying about things like lock escalation, but it makes it hard for individual DBA's and developer's to know what rows are locked.
    Justin

  • SELECT FOR UPDATE with the SKIP LOCK clause

    Hi,
    I have a query regarding the SELECT FOR UPDATE with the SKIP LOCK clause.
    Whether this will be really good for parallel processing.
    Also if we are selecting a set of records in a cursor whether the lock will be done at the records level once we fetch the records?
    Also do we have any known issues with this one?
    We are trying to figure out whether this will fit for business requirement, we are trying to do a implement a threading kind of thing for our stored procedure invocation in background using shell script.
    Any suggestion or feedback on this will be helpful for us.
    Thanks a lot for the support given....
    Regards,
    Basil Abraham.

    http://www.oracle.com/technology/oramag/oracle/08-mar/o28plsql.html
    Please read the above thread for few information...Thanks!

  • "SELECT .. FOR UPDATE" lock event

    Hi All,
    The application will send "SELECT .. FOR UPDATE" statement when end-user click one module on screen.
    Now the system have many end-user need to use this module more than before and elapsed time is 15 seconds per session if have 10 sessions click this module that mean the maximum locked time is 150 seconds (15*10) and source code cannot change.
    My question is which oracle parameter can control about lock timeout in this case or not?
    I tried to check all parameter about lock and timeout of oracle parameter that cannot to solve it but I may missing something.
    Thansks
    Hiko

    taohiko wrote:
    Hi All,
    The application will send "SELECT .. FOR UPDATE" statement when end-user click one module on screen.
    Now the system have many end-user need to use this module more than before and elapsed time is 15 seconds per session if have 10 sessions click this module that mean the maximum locked time is 150 seconds (15*10) and source code cannot change.
    My question is which oracle parameter can control about lock timeout in this case or not?
    I tried to check all parameter about lock and timeout of oracle parameter that cannot to solve it but I may missing something.
    Thansks
    Hikohttp://download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/static.htm#LNPLS603
    By default, the SELECT FOR UPDATE statement waits until the requested row lock is acquired. To change this behavior, use the NOWAIT, WAIT, or SKIP LOCKED clause of the SELECT FOR UPDATE statement.
    If you are adamant as you say that the application cannot be changed (almost never a truthful statement) ... then you are out of luck.

  • Re: Transactions and Locking Rows for Update

    Dale,
    Sounds like you either need an "optimistic locking" scheme, usually
    implemented with timestamps at the database level, or a concurrency manager.
    A concurrency manager registers objects that may be of interest to multiple
    users in a central location. It takes care of notifying interested parties
    (i.e., clients,) of changes made to those objects, using a "notifier" pattern.
    The optimistic locking scheme is relatively easy to implement at the
    database level, but introduces several problems. One problem is that the
    first person to save their changes "wins" - every one else has to discard
    their changes. Also, you now have business policy effectively embedded in
    the database.
    The concurrency manager is much more flexible, and keeps the policy where
    it probably belongs. However, it is more complex, and there are some
    implications to performance when you get to the multiple-thousand-user
    range because of its event-based nature.
    Another pattern of lock management that has been implemented is a
    "key-based" lock manager that does not use events, and may be more
    effective at managing this type of concurrency for large numbers of users.
    There are too many details to go into here, but I may be able to give you
    more ideas in a separate note, if you want.
    Don
    At 04:48 PM 6/5/97 PDT, Dale "V." Georg wrote:
    I have a problem in the application I am currently working on, which it
    seems to me should be easily solvable via appropriate use of transactions
    and database locking, but I'm having trouble figuring out exactly how to
    do it. The database we are using is Oracle 7.2.
    The scenario is as follows: We have a window where the user picks an
    object from a dropdown list. Some of the object's attributes are then
    displayed in that window, and the user then has the option of editing
    those attributes, and at some point hitting the equivalent of a 'save'button
    to write the changes back to the database. So far, so good. Now
    introduce a second user. If user #1 and user #2 both happen to pull up
    the same object and start making changes to it, user #1 could write back
    to the database and then 15 seconds later user #2 could write back to the
    database, completely overlaying user #1's changes without ever knowing
    they had happened. This is not good, particularly for our application
    where editing the object causes it to progress from one state to the next,
    and multiple users trying to edit it at the same time spells disaster.
    The first thing that came to mind was to do a select with intent to update,
    i.e. 'select * from table where key = 'somevalue' with update'. This way
    the next user to try to select from the table using the same key would not
    be able to get it. This would prevent multiple users from being able to
    pull the same object up on their screens at the same time. Unfortunately,
    I can think of a number of problems with this approach.
    For one thing, the lock is only held for the duration of the transaction, so
    I would have to open a Forte transaction, do the select with intent to
    update, let the user modify the object, then when they saved it back again
    end the transaction. Since a window is driven by the event loop I can't
    think of any way to start a transaction, let the user interact with the
    window, then end the transaction, short of closing and re-opening the
    window. This would imply having a separate window specifically for
    updating the object, and then wrapping the whole of that window's event
    loop in a transaction. This would be a different interface than we wanted
    to present to the users, but it might still work if not for the next issue.
    The second problem is that we are using a pooled DBSession approach
    to connecting to the database. There is a single Oracle login account
    which none of the users know the password to, and thus the users
    simply share DBSession resources. If one user starts a transaction
    and does a select with intent to update on one DBSession, then another
    user starts a transaction and tries to do the same thing on the same
    DBSession, then the second user will get an error out of Oracle because
    there's already an open transaction on that DBSession.
    At this point, I am still tossing ideas around in my head, but after
    speaking with our Oracle/Forte admin here, we came to the conclusion
    that somebody must have had to address these issues before, so I
    thought I'd toss it out and see what came back.
    Thanks in advance for any ideas!
    Dale V. Georg
    Indus Consultancy Services [email protected]
    Mack Trucks, Inc. [email protected]
    >
    >
    >
    >
    ====================================
    Don Nelson
    Senior Consultant
    Forte Software, Inc.
    Denver, CO
    Corporate voice mail: 510-986-3810
    aka: [email protected]
    ====================================
    "I think nighttime is dark so you can imagine your fears with less
    distraction." - Calvin

    We have taken an optimistic data locking approach. Retrieved values are
    stored as initial values; changes are stored seperately. During update, key
    value(s) or the entire retieved set is used in a where criteria to validate
    that the data set is still in the initial state. This allows good decoupling
    of the data access layer. However, optimistic locking allows multiple users
    to access the same data set at the same time, but then only one can save
    changes, the rest would get an error message that the data had changed. We
    haven't had any need to use a pessimistic lock.
    Pessimistic locking usually involves some form of open session or DBMS level
    lock, which we haven't implemented for performance reasons. If we do find the
    need for a pessimistic lock, we will probably use cached data sets that are
    checked first, and returned as read-only if already in the cache.
    -DFR
    Dale V. Georg <[email protected]> on 06/05/97 03:25:02 PM
    To: Forte User Group <[email protected]> @ INTERNET
    cc: Richards* Debbie <[email protected]> @ INTERNET, Gardner*
    Steve <[email protected]> @ INTERNET
    Subject: Transactions and Locking Rows for Update
    I have a problem in the application I am currently working on, which it
    seems to me should be easily solvable via appropriate use of transactions
    and database locking, but I'm having trouble figuring out exactly how to
    do it. The database we are using is Oracle 7.2.
    The scenario is as follows: We have a window where the user picks an
    object from a dropdown list. Some of the object's attributes are then
    displayed in that window, and the user then has the option of editing
    those attributes, and at some point hitting the equivalent of a 'save' button
    to write the changes back to the database. So far, so good. Now
    introduce a second user. If user #1 and user #2 both happen to pull up
    the same object and start making changes to it, user #1 could write back
    to the database and then 15 seconds later user #2 could write back to the
    database, completely overlaying user #1's changes without ever knowing
    they had happened. This is not good, particularly for our application
    where editing the object causes it to progress from one state to the next,
    and multiple users trying to edit it at the same time spells disaster.
    The first thing that came to mind was to do a select with intent to update,
    i.e. 'select * from table where key = 'somevalue' with update'. This way
    the next user to try to select from the table using the same key would not
    be able to get it. This would prevent multiple users from being able to
    pull the same object up on their screens at the same time. Unfortunately,
    I can think of a number of problems with this approach.
    For one thing, the lock is only held for the duration of the transaction, so
    I would have to open a Forte transaction, do the select with intent to
    update, let the user modify the object, then when they saved it back again
    end the transaction. Since a window is driven by the event loop I can't
    think of any way to start a transaction, let the user interact with the
    window, then end the transaction, short of closing and re-opening the
    window. This would imply having a separate window specifically for
    updating the object, and then wrapping the whole of that window's event
    loop in a transaction. This would be a different interface than we wanted
    to present to the users, but it might still work if not for the next issue.
    The second problem is that we are using a pooled DBSession approach
    to connecting to the database. There is a single Oracle login account
    which none of the users know the password to, and thus the users
    simply share DBSession resources. If one user starts a transaction
    and does a select with intent to update on one DBSession, then another
    user starts a transaction and tries to do the same thing on the same
    DBSession, then the second user will get an error out of Oracle because
    there's already an open transaction on that DBSession.
    At this point, I am still tossing ideas around in my head, but after
    speaking with our Oracle/Forte admin here, we came to the conclusion
    that somebody must have had to address these issues before, so I
    thought I'd toss it out and see what came back.
    Thanks in advance for
    any
    ideas!
    Dale V. Georg
    Indus Consultancy Services [email protected]
    Mack Trucks, Inc. [email protected]
    ------ Message Header Follows ------
    Received: from pebble.Sagesoln.com by notes.bsginc.com
    (PostalUnion/SMTP(tm) v2.1.9c for Windows NT(tm))
    id AA-1997Jun05.162418.1771.334203; Thu, 05 Jun 1997 16:24:19 -0500
    Received: (from sync@localhost) by pebble.Sagesoln.com (8.6.10/8.6.9) id
    NAA11825 for forte-users-outgoing; Thu, 5 Jun 1997 13:47:58 -0700
    Received: (from uucp@localhost) by pebble.Sagesoln.com (8.6.10/8.6.9) id
    NAA11819 for <[email protected]>; Thu, 5 Jun 1997 13:47:56 -0700
    Received: from unknown(207.159.84.4) by pebble.sagesoln.com via smap (V1.3)
    id sma011817; Thu Jun 5 13:47:43 1997
    Received: from tes0001.macktrucks.com by relay.macktrucks.com
    via smtpd (for pebble.sagesoln.com [206.80.24.108]) with SMTP; 5 Jun
    1997 19:35:31 UT
    Received: from dale by tes0001.macktrucks.com (SMI-8.6/SMI-SVR4)
    id QAA04637; Thu, 5 Jun 1997 16:45:51 -0400
    Message-ID: <[email protected]>
    Priority: Normal
    To: Forte User Group <[email protected]>
    Cc: "Richards," Debbie <[email protected]>,
    "Gardner," Steve <[email protected]>
    MIME-Version: 1.0
    From: Dale "V." Georg <[email protected]>
    Subject: Transactions and Locking Rows for Update
    Date: Thu, 05 Jun 97 16:48:37 PDT
    Content-Type: text/plain; charset=US-ASCII; X-MAPIextension=".TXT"
    Content-Transfer-Encoding: quoted-printable
    Sender: [email protected]
    Precedence: bulk
    Reply-To: Dale "V." Georg <[email protected]>

  • Transactions and Locking Rows for Update

    I have a problem in the application I am currently working on, which it
    seems to me should be easily solvable via appropriate use of transactions
    and database locking, but I'm having trouble figuring out exactly how to
    do it. The database we are using is Oracle 7.2.
    The scenario is as follows: We have a window where the user picks an
    object from a dropdown list. Some of the object's attributes are then
    displayed in that window, and the user then has the option of editing
    those attributes, and at some point hitting the equivalent of a 'save' button
    to write the changes back to the database. So far, so good. Now
    introduce a second user. If user #1 and user #2 both happen to pull up
    the same object and start making changes to it, user #1 could write back
    to the database and then 15 seconds later user #2 could write back to the
    database, completely overlaying user #1's changes without ever knowing
    they had happened. This is not good, particularly for our application
    where editing the object causes it to progress from one state to the next,
    and multiple users trying to edit it at the same time spells disaster.
    The first thing that came to mind was to do a select with intent to update,
    i.e. 'select * from table where key = 'somevalue' with update'. This way
    the next user to try to select from the table using the same key would not
    be able to get it. This would prevent multiple users from being able to
    pull the same object up on their screens at the same time. Unfortunately,
    I can think of a number of problems with this approach.
    For one thing, the lock is only held for the duration of the transaction, so
    I would have to open a Forte transaction, do the select with intent to
    update, let the user modify the object, then when they saved it back again
    end the transaction. Since a window is driven by the event loop I can't
    think of any way to start a transaction, let the user interact with the
    window, then end the transaction, short of closing and re-opening the
    window. This would imply having a separate window specifically for
    updating the object, and then wrapping the whole of that window's event
    loop in a transaction. This would be a different interface than we wanted
    to present to the users, but it might still work if not for the next issue.
    The second problem is that we are using a pooled DBSession approach
    to connecting to the database. There is a single Oracle login account
    which none of the users know the password to, and thus the users
    simply share DBSession resources. If one user starts a transaction
    and does a select with intent to update on one DBSession, then another
    user starts a transaction and tries to do the same thing on the same
    DBSession, then the second user will get an error out of Oracle because
    there's already an open transaction on that DBSession.
    At this point, I am still tossing ideas around in my head, but after
    speaking with our Oracle/Forte admin here, we came to the conclusion
    that somebody must have had to address these issues before, so I
    thought I'd toss it out and see what came back.
    Thanks in advance for any ideas!
    Dale V. Georg
    Indus Consultancy Services [email protected]
    Mack Trucks, Inc. [email protected]
    [email protected]------------------

    I have a problem in the application I am currently working on, which it
    seems to me should be easily solvable via appropriate use of transactions
    and database locking, but I'm having trouble figuring out exactly how to
    do it. The database we are using is Oracle 7.2.
    The scenario is as follows: We have a window where the user picks an
    object from a dropdown list. Some of the object's attributes are then
    displayed in that window, and the user then has the option of editing
    those attributes, and at some point hitting the equivalent of a 'save' button
    to write the changes back to the database. So far, so good. Now
    introduce a second user. If user #1 and user #2 both happen to pull up
    the same object and start making changes to it, user #1 could write back
    to the database and then 15 seconds later user #2 could write back to the
    database, completely overlaying user #1's changes without ever knowing
    they had happened. This is not good, particularly for our application
    where editing the object causes it to progress from one state to the next,
    and multiple users trying to edit it at the same time spells disaster.
    The first thing that came to mind was to do a select with intent to update,
    i.e. 'select * from table where key = 'somevalue' with update'. This way
    the next user to try to select from the table using the same key would not
    be able to get it. This would prevent multiple users from being able to
    pull the same object up on their screens at the same time. Unfortunately,
    I can think of a number of problems with this approach.
    For one thing, the lock is only held for the duration of the transaction, so
    I would have to open a Forte transaction, do the select with intent to
    update, let the user modify the object, then when they saved it back again
    end the transaction. Since a window is driven by the event loop I can't
    think of any way to start a transaction, let the user interact with the
    window, then end the transaction, short of closing and re-opening the
    window. This would imply having a separate window specifically for
    updating the object, and then wrapping the whole of that window's event
    loop in a transaction. This would be a different interface than we wanted
    to present to the users, but it might still work if not for the next issue.
    The second problem is that we are using a pooled DBSession approach
    to connecting to the database. There is a single Oracle login account
    which none of the users know the password to, and thus the users
    simply share DBSession resources. If one user starts a transaction
    and does a select with intent to update on one DBSession, then another
    user starts a transaction and tries to do the same thing on the same
    DBSession, then the second user will get an error out of Oracle because
    there's already an open transaction on that DBSession.
    At this point, I am still tossing ideas around in my head, but after
    speaking with our Oracle/Forte admin here, we came to the conclusion
    that somebody must have had to address these issues before, so I
    thought I'd toss it out and see what came back.
    Thanks in advance for any ideas!
    Dale V. Georg
    Indus Consultancy Services [email protected]
    Mack Trucks, Inc. [email protected]
    [email protected]------------------

  • Is there a way to BULK COLLECT with FOR UPDATE and not lock ALL the rows?

    Currently, we fetch a cursor on a few million rows using BULK COLLECT.
    In a FORALL loop, we update the rows.
    What is happening now, is that we run this procedure at the same time, and there is another session running a MERGE statement on the same table, and a DEADLOCK is created between them.
    I'd like to add to the cursor the FOR UPDATE clause, but from what i've read,
    it seems that this will cause ALL the rows in the cursor to become locked.
    This is a problem, as the other session is running MERGE statements on the table every few seconds, and I don't want it to fail with ORA-0054 (resource busy).
    What I would like to know is if there is a way, that only the rows in the
    current bulk will be locked, and all the other rows will be free for updates.
    To reproduce this problem:
    1. Create test table:
    create table TEST_TAB
    ID1 VARCHAR2(20),
    ID2 VARCHAR2(30),
    LAST_MODIFIED DATE
    2. Add rows to test table:
    insert into TEST_TAB (ID1, ID2, LAST_MODIFIED)
    values ('416208000770698', '336015000385349', to_date('15-11-2009 07:14:56', 'dd-mm-yyyy hh24:mi:ss'));
    insert into TEST_TAB (ID1, ID2, LAST_MODIFIED)
    values ('208104922058401', '336015000385349', to_date('15-11-2009 07:11:15', 'dd-mm-yyyy hh24:mi:ss'));
    insert into TEST_TAB (ID1, ID2, LAST_MODIFIED)
    values ('208104000385349', '336015000385349', to_date('15-11-2009 07:15:13', 'dd-mm-yyyy hh24:mi:ss'));
    3. Create test procedure:
    CREATE OR REPLACE PROCEDURE TEST_PROC IS
    TYPE id1_typ is table of TEST_TAB.ID1%TYPE;
    TYPE id2_typ is table of TEST_TAB.ID2%TYPE;
    id1_arr id1_typ;
    id2_arr id2_typ;
    CURSOR My_Crs IS
    SELECT ID1, ID2
    FROM TEST_TAB
    WHERE ID2 = '336015000385349'
    FOR UPDATE;
    BEGIN
    OPEN My_Crs;
    LOOP
    FETCH My_Crs bulk collect
    INTO id1_arr, id2_arr LIMIT 1;
    Forall i in 1 .. id1_arr.COUNT
    UPDATE TEST_TAB
    SET LAST_MODIFIED = SYSDATE
    where ID2 = id2_arr(i)
    and ID1 = id1_arr(i);
    dbms_lock.sleep(15);
    EXIT WHEN My_Crs%NOTFOUND;
    END LOOP;
    CLOSE My_Crs;
    COMMIT;
    EXCEPTION
    WHEN OTHERS THEN
    RAISE_APPLICATION_ERROR(-20000,
    'Test Update ' || SQLCODE || ' ' || SQLERRM);
    END TEST_PROC;
    4. Create another procedure to check if table rows are locked:
    create or replace procedure check_record_locked(p_id in TEST_TAB.ID1%type) is
    cursor c is
    select 'dummy'
    from TEST_TAB
    WHERE ID2 = '336015000385349'
    and ID1 = p_id
    for update nowait;
    e_resource_busy exception;
    pragma exception_init(e_resource_busy, -54);
    begin
    open c;
    close c;
    dbms_output.put_line('Record ' || to_char(p_id) || ' is not locked.');
    rollback;
    exception
    when e_resource_busy then
    dbms_output.put_line('Record ' || to_char(p_id) || ' is locked.');
    end check_record_locked;
    5. in one session, run the procedure TEST_PROC.
    6. While it's running, in another session, run this block:
    begin
    check_record_locked('208104922058401');
    check_record_locked('416208000770698');
    check_record_locked('208104000385349');
    end;
    7. you will see that all records are identified as locked.
    Is there a way that only 1 row will be locked, and the other 2 will be unlocked?
    Thanks,
    Yoni.

    I don't have database access on weekends (look at it as a template)
    suppose you
    create table help_iot
    (bucket number,
    id1    varchar2(20),
    constraint help_iot_pk primary key (bucket,id1)
    organization index;not very sure about the create table syntax above.
    declare
      maximal_bucket number := 10000; -- will update few hundred rows at a time if you must update few million rows
      the_sysdate date := sysdate;
    begin
      truncate table help_iot;
      insert into help_iot
      select ntile(maximal_bucket) over (order by id1) bucket,id1
        from test_tab
       where id2 = '336015000385349';
      for i in 1 .. maximal_bucket
      loop
        select id1,id2,last_modified
          from test_tab
         where id2 = '336015000385349'
           and id1 in (select id1
                         from help_iot
                        where bucket = i
           for update of last_modified;
        update test_tab
           set last_modified = the_sysdate
         where id2 = '336015000385349'
           and id1 in (select id1
                         from help_iot
                        where bucket = i
        commit;
        dbms_lock.sleep(15);
      end loop;
    end;Regards
    Etbin
    introduced the_sysdate if last_modified must be the same for all updated rows
    Edited by: Etbin on 29.11.2009 16:48

Maybe you are looking for

  • CA-Signed certificate: Received fatal alert: bad_certificate

    Hello. I am still trying to get rmi ssl to work in the way I want (see my post http://forums.sun.com/thread.jspa?threadID=5351278&tstart=15 ). I read that CA signed certificates are preferred to self signed certificates due to several reasons. Due to

  • Multiple lines in BDC

    Hi, I have to deal with multiple lines in BDC. I am using the FM READ_TEXT. Now I am getting the multiple lines text through above FM in my itab. Then I made loop at itab & under this I wrote the screen-fields. But I m getting only last value in my s

  • Custom Design With Squares as Buttons  - Help

    This may be a simple task, the method however is just bypassing me ... can anyone help please? I would like to design a page, with five interlocking squares of different sizes. It's not an even tessellation, therefore I am doing this in Illustrator,

  • Re: Toshiba Configuring System

    this is for windows vista: let the Configuring System run a few times... who knows what its doing... on the 5th or 6th time the computer reboots and config setup is running hit "windows key" to bring up start bar. right click on "scripts" icon runnin

  • RCIRAS0274 - Contact system admin error

    Hello to all,             I am trying to open some of the canned reports in the infoview but sometimes i get this error <b>"<i>RCIRAS0274 - Contact system admin error</i></b>". If i try couple of times the same report opens again. So not sure what is