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,
Davidyes.
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 LundmarkAlso 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 PMBolev 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
PremOracle 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 -
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
MauriceWhen 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
Hikotaohiko 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." - CalvinWe 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
-
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