Select or Select....for update nowait (data write concurrency issue)
Hello everyone,
I am working on a jsp/servlet project now, and got questions about which is the better way to deal with concurrent writing issues.
The whole senario is described as following:
First each user is viewing his own list of several records, and each record has a hyperlink through which user can modify it. After user clicks that link, there will be a popup window pre-populated with the values of that record, then user can do the modifications. After he is done, he can either click "Save " to save the change or "Cancel" to cancel it.
Method1---This is the method I am using right now.
I did not do any special synchronization measures, so if user 1 and user2 click the link of same record, they will modify the record
at the same time, then whose updates will take effect depends on who submits the request later. If user1 submitted first, then user 2, user1
will not see his updates. I know with this method, we will have the problem of "Lost Updates", but this is the simplest and efficient way to handle this issue.
Method2--This is the method I am hesitating.
I am considering to use "Select....for update nowait " to lock a record when user1 has selected one record and intended to modify it. If user2 wanted to modify the same record, he is not allowed. ( by catching the sql exception.)But the issue I am concerned about is because the "select .. For update" action and "Update action" are not so consecutive as many transaction examples described. There could be a
big interval between " select " and "update" actions. You could not predict user's behavior, maybe after he open the popup window, it took him a while to make up his decision, or even worse, he was interrupted by other things and went away for the whole morning?.Then the lock is just held until he releases it.
And another issue is if he clicks "cancel" to cancel his work, if I use method1, I don't need to interact with server-side at all, but if user method2, I still need to interact with the server to release the lock.
Can someone give me some advice ? What do you do to deal with similar situation? If I did not make clear of the question, please let me know.
Thanks in advance !
Rachel
Hi Rachel,
Congratulation, you have found a way to overcome your programming business logic.
Have you ever consider that the solution of using CachedRowset concept yet to be included in j2se 1.5 tiger next year too prove workable under the scenario , whereby you can disconnect from the database after you have execute your query and reconnect again if you have to do transactional activity later, so that the loading overhead as well as the data pooling activity could be well balanced off.
Although rowset is still not an official API now, but its potential to me is worth consideration.
I have written a simple but crude cut JSP programme posted on this forum under the heading "Interesting CachedRowset JSP code to share " to demonstrate the concept of CachedRowset and hoping that the Java guru or the developer could provide feedback on how to imporve on the programming logic or methodology.
Thanks!!
Similar Messages
-
Help, question about "select ... for update nowait"
There is a proc code. In the beginning of the code, I used a SQL "select ... for update nowait" in order to prevent from another proc executing at the same time. When the case happens, "-54, ORA-00054: resource busy and acquire with NOWAIT specified" will be printed in the screen.
But there is a question: I need to print sth to indicate "another proc is running". I used "if (sqlca.sqlcode == -54)" as precondition, such as:
if (sqlca.sqlcode == -54) {
printf("There is another proc running.\n");
However, this line will not be printed. I doubt that the code quits directly when using "select ... for update nowait" so as not to set value (-54) to sqlca.sqlcode.
So, could you suggest whether there is another way that I can use to print "There is another proc running" when another proc is running?
Thx a lot for your kindly reply.Yes, that link. Scroll down a bit and you will see:
The calling application gets a PL/SQL exception, which it can process using the error-reporting functions SQLCODE and SQLERRM in an OTHERS handler. Also, it can use the pragma EXCEPTION_INIT to map specific error numbers returned by raise_application_error to exceptions of its own, as the following Pro*C example shows:
EXEC SQL EXECUTE
/* Execute embedded PL/SQL block using host
variables v_emp_id and v_amount, which were
assigned values in the host environment. */
DECLARE
null_salary EXCEPTION;
/* Map error number returned by raise_application_error
to user-defined exception. */
PRAGMA EXCEPTION_INIT(null_salary, -20101);
BEGIN
raise_salary(:v_emp_id, :v_amount);
EXCEPTION
WHEN null_salary THEN
INSERT INTO emp_audit VALUES (:v_emp_id, ...);
END;
END-EXEC;
This technique allows the calling application to handle error conditions in specific exception handlers. -
Ansi SQL for "select ... for update nowait"
Hi, All,
I have a sql
select ... for update nowait
My boss wants it to be ANSI compliant.
I am not familiar with ANSI SQL.
What should be the syntax in Ansi?
Thanks a lot!I resent having the lowest salary :-)Sorry John, it's probably due to the exchange rate of sterling against the canuck dollar right now.
SQL> select empno, ename, sal, job, mgr from emp;
EMPNO ENAME SAL JOB MGR
7369 SPENCER 800 CLERK 7902
7499 VERREYNNE 1600 SALESMAN 7698
7521 VAN WIJK 1250 SALESMAN 7698
7566 MAINGUY 2975 MANAGER 7839
7654 KISHORE 1250 SALESMAN 7698
7698 BARRY 2850 MANAGER 7839
7782 BOEHMER 2695 MANAGER 7839
7788 PADFIELD 3000 ANALYST 7566
7839 SCHNEIDER 5500 PRESIDENT
7844 GASPAROTTO 1500 SALESMAN 7698
7876 CAVE 1100 CLERK 7788
7900 CLARKE 950 CLERK 7698
7902 JAFFAR 3000 ANALYST 7566
7934 ROBERTSON 1430 CLERK 7782
14 rows selected.
SQL> Cheers, APC -
[ORACLE 9] Select For Update Nowait - Managing the Nowait
Hi,
Our application ( Oracle E Business R11) has a Form that allows Updates.
The problem is, when a user updates a record in the form, we want to prevent another user to open the same form, to avoid locks.
So I thought that I could
a) issue a 'select ...for update nowait',
b) get a code from Oracle
c )and use this code to prevent the form to be reopened.
I tried catching the Nowait in the exception section but I cannot get it to work.
Here is my code:
declare
v_var varchar2(40) := '---';
lv_nom tmp_delegue_jbm.del_nom%type;
begin
v_var := 'Phase 1';
select del_nom
into lv_nom
from tmp_delegue_jbm
where del_id = 3
for update of del_nom nowait;
dbms_output.put_line( 'Phase: ' || v_var );
v_var := 'Phase 2';
update tmp_delegue_jbm
set del_nom = del_nom || ' in'
where del_id = 3;
dbms_output.put_line( 'Phase: ' || v_var );
exception
when others then -- Should deal with the nowait situation
dbms_output.put_line( 'Error: ' || v_var || ' - ' || sqlerrm );
end;
[End Code]
Many thanksFar easier to poke a value into memory using DBMS_APPLICATION_INFO.SET_ACTION or SET_MODULE and have any session calling the form check first to see of another session has it already opened. Just make sure your exception handlers clear the lock.
http://www.morganslibrary.org/reference/dbms_applic_info.html -
Should i use SELECT for update NOWAIT ?
Hi:
Do I need to use, in my pl/sql triggers and procedures, the SELECT FOR UPDATE NOWAIT sentence, to avoid locks before using update table sentences ? Is it common to use it on stored procedures and triggers?
Thanks
Joao OliveiraFirst, what, exactly do you mean by "avoid locks"? I was interpreting that to mean "I want to avoid creating locks in my session that might block someone else", not "I want to avoid having my SELECT wait for locks to be released-- I want it to fail immediately". If you meant the latter, then SELECT ... FOR UPDATE NOWAIT would be what you want. If you meant the former, then pessimistic locking is not what you want.
Second, what sort of Oracle Forms architecture do you have? Are you still using old-school client-server applications? Or are you using a three-tiered approach? As Tom discusses in that thread, pessimistic locking is only an option when your client application is able to maintain database state across calls (i.e. client/server systems) not when you have stateless connections (which is the norm in the three-tier model). The old client-server versions of Forms would automatically and transparently do pessimistic locking. Since you didn't mention anything about your architecture, most of us probably assumed the more common stateless client architecture (note how Tom's answers progress over the 5 years in that thread as client/server architecture became less and less common).
Third, while your question is appropriate for either the Database - General forum or the SQL and PL/SQL forum, that generally means that you are free to post it either forum, not that it should be posted in both. The vast majority of the folks that hang out in one forum hang out in the other. It's also rather frustrating to answer a post in one forum only to discover that there is another post in a different forum where someone else had already covered the same points half an hour earlier or to discover that there was additional information in another thread that might have changed your answer.
Fourth, if you are going to do pessimistic locking, that requires that you are able to maintain state across various database calls, that you are locking on the lowest possible level of granularity, and that you are able to time out sessions relatively aggressively to ensure that someone doesn't open a record, thereby locking it, go to lunch (or have their system die) and then block everyone else from working. Assuming that is the case, and that you have some reasonable way to handle the error that gets generated other than simply retrying the operation, adding NOWAIT is certainly an option. Most applications, particularly those getting written today, cannot guarantee all these things, so pessimistic locking is generally not appropriate there.
Looking at your other thread (where there is new information that would be useful in this discussion, one of the reasons that multiple threads are generally a bad idea), it seems that you have an ERP application and you are concerned about the performance of entering orders. Obviously, there shouldn't be any locking issues on the ORDER or ORDER_DETAILS tables, assuming that multiple users aren't going to be inserting the same order at the same time. The contention would almost certainly come when multiple orders are trying to update the STOCK and INVENTORY tables, since multiple orders presumably rely on the same rows in those tables. In that case, I'm not sure what adding a NOWAIT would buy you-- unless you were going to roll back the entire order because someone is updating the STOCK row for #2 pencils and your order has an item of #2 pencils, you'd have to keep retrying the operation until you were able to modify the STOCK row, which would be less efficient than just letting that update block until the row was free.
Now, you could certainly redesign the application to minimize that contention by not trying to update what I assume are aggregate tables like STOCK and INVENTORY directly as part of your OLTP processing or, at least, by minimizing the time that you're locking a row. You could, for example, make STOCK and INVENTORY materialized views rather than tables that refresh ON COMMIT, which should decrease the time that your locks are held. You could also have those tables refreshed asynchronously, which would be even more efficient but may require that you reasses your holdback requirements.
Justin -
Hi everyone!
I have procedure that looks like this:
procedure set_expired_users(
p_QID integer,
p_Value integer default 1)
is
l_mdate timestamp(3) := null;
begin
l_mdate := get_mdate(p_Value);
MERGE INTO cached_lists cl
USING (SELECT distinct s.rootof as list_id, p_Value as is_expired, l_mdate as mdate
FROM zzz_userrelflat f, zzz_users u, zzz_temp_nn z, speclists s, lists_table lt
WHERE u.grp <> 1
AND f.userm = u.id
AND lt.id = z.id
AND f.userg = lt.ra
AND z.qid = p_QID
AND userm <> -2
AND s.ruser = userm) t
ON (cl.list_id = t.list_id)
when matched then
UPDATE SET cl.is_expired = t.is_expired, cl.mdate = decode(t.mdate, null, cl.mdate, t.mdate)
when not matched then
INSERT VALUES (t.list_id, t.is_expired, l_mdate);
end set_expired_users;As you can see there is no commit, commit executes in other stored procedures after that. in some cases I have bottleneck(enq TX), I rewrote procedure:
procedure set_expired_users(
p_QID integer,
p_Value integer default 1)
is
l_mdate timestamp(3) := null;
busy_lock exception;
PRAGMA exception_init(busy_lock,-54);
cursor cur_upd is
SELECT 1 from cached_lists cl where cl.list_id in (SELECT distinct s.rootof as list_id
FROM zzz_userrelflat f, zzz_users u, zzz_temp_nn z, speclists s, lists_table lt
WHERE u.grp <> 1
AND f.userm = u.id
AND lt.id = z.id
AND f.userg = lt.ra
AND z.qid = p_QID
AND userm <> -2
AND s.ruser = userm) FOR UPDATE NOWAIT;
begin
open cur_upd;
l_mdate := get_mdate(p_Value);
MERGE INTO cached_lists cl
USING (SELECT distinct s.rootof as list_id, p_Value as is_expired, l_mdate as mdate
FROM zzz_userrelflat f, zzz_users u, zzz_temp_nn z, speclists s, lists_table lt
WHERE u.grp <> 1
AND f.userm = u.id
AND lt.id = z.id
AND f.userg = lt.ra
AND z.qid = p_QID
AND userm <> -2
AND s.ruser = userm) t
ON (cl.list_id = t.list_id)
when matched then
UPDATE SET cl.is_expired = t.is_expired, cl.mdate = decode(t.mdate, null, cl.mdate, t.mdate)
when not matched then
INSERT VALUES (t.list_id, t.is_expired, l_mdate);
close cur_upd;
exception
when busy_lock then
null;
end set_expired_users;Is this a good method to exclude enq TX?
Sincerely,
Pavel.In my opinion, you shouldn't rewrite that procedure, but you should rethink (ie. streamline) the overall transaction and try to reduce the wait times between the procedure call and the commit/rollback.
-
Problem with "SELECT...FOR UPDATE OF..." and "POST command" combination
Problem in committing transactions in Multiple Forms (Oracle Forms) with POST built-in command:
Consider that the following statements are written in WHEN-WINDOW-CLOSED trigger of a called form.
Statements in called form (Form name: FORM_CHILD):
go_block('display_block') ;
do_key('execute_query') ;
-- Data from table_b will be populated in this block, based on the value of COLUMN_1 obtained
-- from TABLE_A.
-- Example: If the value of COLUMN_1 is 10, then all the matching records from TABLE_B, which
-- are inserted with value 10 in TABLE_B.COLUMN_1 will be fetched and shown here.
if user_choice = 'YES' then
commit ;
else
rollback ;
end if ;
Statements in calling forms:
There are two calling forms having following statements and it is going to call the above said called form.
CALLING FORM 1
Statements in KEY-COMMIT trigger:
post;
call_form(form_child, no_activate) ;
Statements in ON-INSERT trigger:
select column_1
from table_a
for update of column_1
where column_2 = 'X' ;
update table_a
set column_1 = column_1 + 1
where column_2 = 'X' ;
insert into table_b ...;
insert into table_b ...; Statements in KEY-COMMIT trigger:
post;
call_form(form_child, no_activate) ;
CALLING FORM 2:
Statements in ON-INSERT trigger:
select column_1
from table_a
for update of column_1
where column_2 = 'X' ;
update table_a
set column_1 = column_1 + 1
where column_2 = 'X' ;
insert into table_b ...;
insert into table_b ...;
insert into table_b ...;
Our understanding:
Assume that both the forms are running from two different machines/instances, issuing commit at the same time. In this case, forms will start executing the statements written in ON-INSERT trigger, the moment POST command is executed. Though the commit is issued at the same time, according to oracle, only one of the request will be taken for processing first. Assume that calling form 1 is getting processed first.
So, it fetches the value available in COLUMN_1 of TABLE_A and locks the row from further select, update, etc. as SELECT...FOR UPDATE command is used (note that NOWAIT is not given, hence the lock will be released only when COMMIT or ROLLBACK happens) and proceed executing further INSERT statements. Because of the lock provided by the SELECT...FOR UPDATE command, the statements in calling form 2 will wait for the resource.
After executing the INSERT statements, the FORM_CHILD is called. The rows inserted in to TABLE_A will be queried and shown. The database changes will be committed when user closes the window (as COMMIT is issued in its WHEN-WINDOW-CLOSED trigger). Then the SELECT...FOR UPDATE lock will be released and calling form 2's statements will be executed.
Actual happenings or Mis-behavior:
Calling form 2 starts executing INSERT statements instead of waiting for SELECT...FOR UPDATE lock. Also, the value selected from TABLE_A.COLUMN_1 is same in both the calling forms, which is wrong.
The rows inserted into TABLE_B are having similar COLUMN_1 values in calling form 2 and they are fetched and shown in the called form FORM_CHILD.
Note that in calling form 2 also POST only is issued, but the changes posted there are accessible in calling form 1 also, which is wrong.
Kindly suggest us as to how to fix above problem. It will be much use, if you can send us the information regarding the behavior of Oracle Forms POST built-in also.
Our mail ID: [email protected]
Thanks a lot in advance.You have several problems:
1. On-Insert will ONLY run if you have created a new record in a base-table block. If you haven't done that, then the POST command will not cause it to run.
2. Select for update without a "no wait" will lock records for the first form, but when the second form tries this, it will hit the ORA-00054 exception, and will NOT wait. The only way you could make it wait is to issue an UPDATE sql command, which is not such a good way to go.
All POST does is issues SQL insert or update commands for any changes the user has made to records in a form's base-table blocks, without following with a Commit command.
Also understand that Commit is the same as Commit_Form, and Rollback is the same as Clear_Form. You should read up on these in the Forms help topics. -
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) -
Jdbc mysql "select ... for update" and isolation level...
Dear, I am now writing an application, in which some worker threads will get a waiting job from database (mysql) and perform the processing.
To avoid workers getting the same job id, I have studied the topics about locks, isolation level, and something like "select ... for update".
The storage engine being used is innoDB. Actually the problem seems solved after using "select ... for update" to get the id, but I am just curious that do I also need to care about the isolation level. It is because when I do some experiments by setting the isolation level to serializable, but NOT using "SELECT ... FOR UPDATE" (just simple select), exception something like "deadlock found and try to restart transaction" occurs. Is there any relationship between these two things? Any comments are welcome!! Thanks!!!ashipj wrote:
can u plz provide me with the code (connection string). Am new to Mysql.
And also the driver u are using.
Thank youDon't hijack other's topics. Kindly start your own. Don't do that before you read the [Sun JDBC tutorial|http://java.sun.com/docs/books/tutorial/jdbc/index.html] and the [MySQL JDBC documentation|http://dev.mysql.com/doc/refman/5.0/en/connector-j.html]. -
"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. -
JDBC Problem: "select * from NAMES for update of FIRSTNAME"
I am using Oracle 8 and JDBC thin driver. Is there any reason
why when I try to use the statement:
"select * from NAMES for update of FIRSTNAME"
it does NOT work in JDBC?
However when I do the statement in SQL-Plus it works fine.
If anyone has used this statement with success, please let me
know that it actually works, so that I know there is something
wrong with me!
Any code snippets would be very helpful.
Could it be the thin driver?
Please help! Thanks in advance.
nullThomas Gutzmann (guest) wrote:
: James,
: for this command you need transactional control, which is not
: possible with JDBC - if I'm not wrong. You can circumvent it
with
: something like:
: select x into vOld from t where id=4711;
: vNew := 0.815;
: update t set x = vNew where id = 4711 and x = vOld;
: Another option would be to write a stored PL/SQL procedure that
: runs the whole transaction.
: Cheers
: Thomas
: James Ward (guest) wrote:
: : I am using Oracle 8 and JDBC thin driver. Is there any
reason
: : why when I try to use the statement:
: : "select * from NAMES for update of FIRSTNAME"
: : it does NOT work in JDBC?
: : However when I do the statement in SQL-Plus it works fine.
: : If anyone has used this statement with success, please let me
: : know that it actually works, so that I know there is
something
: : wrong with me!
: : Any code snippets would be very helpful.
: : Could it be the thin driver?
: : Please help! Thanks in advance.
I don't think this is correct. I have used select for update
with no problems. you can send a "set transaction control"
via sql, I believe, but you shouldn't need to do so...
Maureen
null -
Select...for update and close()
I am seeing unexpected behaviour when working with select for update, and I hope to get some clarification about it. I have RTFM and checked out any online information I could find, but didn't see too much about row level locks. See below for the problem I am encountering
We have an application with lots of threads on multiple nodes that uses a combination of row level locking and status flags to mark a row as being processed.
We are locking the rows, and then after completing the select ... for update statement we are closing the JDBC statement.
On executing the statement.close() it appears as though the row level lock is lost. Can anyone confirm this behaviour, or tell me that I am misreading the behaviour that I am seeing.
Thanks in advance,
Robert DawsonI'd expect this behavior regardless of whether autocommit was on. If a statement is closed, any locks held by that statement must be released. If they weren't, no other statement would have permission to remove the locks, so the rows would remain locked indefinitely.
Justin -
The lock for "select ... for update"
1. select * from tbl for update;
2. SELECT p.spid, a.serial#, c.object_name, b.session_id, b.oracle_username, b.os_user_name FROM v$process p, v$session a, v$locked_object b, all_objects c WHERE p.addr = a.paddr AND a.process = b.process AND c.object_id = b.object_id
Why there is two records with the same session_id:
1 14728 11961 TBL 290 STAR bil
2 14732 50904 TBL 290 STAR bil
The SQL "select ... for update" will generate two locks?I get one lock:
SQL> SELECT p.spid, a.serial#, c.object_name, b.session_id, b.oracle_username, b.os_user_name FROM v
$process p, v$session a, v$locked_object b, all_objects c WHERE p.addr = a.paddr AND a.process = b.p
rocess AND c.object_id = b.object_id;
no rows selected
SQL> select * from emp for update;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 17-12-1980 00:00:00 800 20
7499 ALLEN SALESMAN 7698 20-02-1981 00:00:00 1600 300 30
7521 WARD SALESMAN 7698 22-02-1981 00:00:00 1250 500 30
7566 JONES MANAGER 7839 02-04-1981 00:00:00 2975 20
7654 MARTIN SALESMAN 7698 28-09-1981 00:00:00 1250 1400 30
7698 BLAKE MANAGER 7839 01-05-1981 00:00:00 2850 30
7782 CLARK MANAGER 7839 09-06-1981 00:00:00 2450 10
7788 SCOTT ANALYST 7566 09-12-1982 00:00:00 3000 20
7839 KING PRESIDENT 17-11-1981 00:00:00 5000 10
7844 TURNER SALESMAN 7698 08-09-1981 00:00:00 1500 0 30
7876 ADAMS CLERK 7788 12-01-1983 00:00:00 1100 20
7900 JAMES CLERK 7698 03-12-1981 00:00:00 950 30
7902 FORD ANALYST 7566 03-12-1981 00:00:00 3000 20
7934 MILLER CLERK 7782 23-01-1982 00:00:00 1300 10
14 rows selected.
SQL> SELECT p.spid, a.serial#, c.object_name, b.session_id, b.oracle_username, b.os_user_name FROM v
$process p, v$session a, v$locked_object b, all_objects c WHERE p.addr = a.paddr AND a.process = b.p
rocess AND c.object_id = b.object_id;
SPID SERIAL# OBJECT_NAME SESSION_ID ORACLE_USERNAME OS_USER_NAME
2536 4 EMP 25 HOEK hoek
1 row selected.What database version are you using?
(the result of: select * from v$version; ) -
FOR UPDATE NOWAIT Fails to Detect Lock
Locking a bitmap indexed row would cause other rows locked. I heard that, if FOR UPDATE NOWAIT is used on these accidentally locked rows (Oracle SQL High Performance Turning by Prentice hall), it may not be able to detect the lock. Is it true? I cannot find related documenation from Oracle's manual. And, what should we do to prevent an incorrect lock status returned by FOR UPDATE NOWAIT?
SELECT FOR UPDATE NOWAIT detects locks affected DATA blocks.
Look the example below:
SQL> create table t1 (id number, bit_col number);
Table created.
SQL> begin
2 insert into t1 values(0,1);
3 insert into t1 values(1,1);
4 insert into t1 values(2,2);
5 insert into t1 values(3,3);
6 insert into t1 values(4,4);
7 end;
8 /
PL/SQL procedure successfully completed.
SQL> commit;
Commit complete.
SQL> create bitmap index t1_bit on t1(bit_col);
Index created.Now in session 1 we change the bitmap-indexed column and it affects
index node:
SQL> update t1
2 set bit_col = 4
3 where id = 2;
1 row updated.In accordance to bitmap index structure this operator locks the index section
the locked row pertains to:
2th session waits for the lock release even when it tries to lock another row -
two rows pertain to the same index section which is locked by the first session:
SQL> update t1
2 set bit_col = 2
3 where id = 3;After rollback in the first session the second one gets the resource:
SQL> update t1
2 set bit_col = 2
3 where id = 3;
1 row updated.Now lets do rollback in both and repeate the first UPDATE in the first session:
SQL> update t1
2 set bit_col = 4
3 where id = 2;
1 row updated.In the second session we can lock the row (not index section) using
SELECT FOR UPDATE:(in contrast with UPDATE statement which changes
indexed column):
SQL> select * from t1 where id=3 for update nowait;
ID BIT_COL
3 3But certainly we detect row-level lock in the data block for ID = 2:
SQL> select * from t1 where id=2 for update nowait;
select * from t1 where id=2 for update nowait
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specifiedRgds. -
Oracle Version: 10.2.0.5
O/S : Redhat
Hi,
I have a select statement that is wrapped in the FOR UPDATE NOWAIT clause. This is embedded in a stored procedure and this stored procedure may be called concurrently by multiple threads from a .net application.
Off late i have noticed that the proc has been returning the same value to 2 different calls - this defeats the purpose of row-level locking that FOR UPDATE NOWAIT does. I did notice that the procedure calls from the .net application where 100th of a millisecond apart.
Is there any workaround to avoid the same row being returned to different calls? or is this a known behaviour and i just have to live with it?
Edited by: brainstormer on May 6, 2013 12:56 PMThis is part of the SP that performs the lock, updates the queue table so that record is marked as In Process so it is not returned to another process when it is already In Process.
Thought it may sound far fetched, my theory is that even before session 1 completes the SELECT statement, session 2 comes in and run the select statement. Since session 1 has not completed and has not locked the row yet - oracle returns the same row to both.
Is this a possible scenario?
PRAGMA AUTONOMOUS_TRANSACTION;
lock_detected EXCEPTION;
PRAGMA EXCEPTION_INIT(lock_detected, -54);
BEGIN
BEGIN
SELECT q.request_id, q.process_id
INTO o_request_id, o_process_id
FROM PROCESS_QUEUE q
WHERE q.process_id IN (
SELECT process_id
FROM (
SELECT l.process_id
FROM PROCESS_QUEUE L, REQUESTS r
WHERE L.request_id = r.request_id
AND r.manifest_only = NVL(io_manifest_only,r.manifest_only)
AND r.status = 'INP'
AND ((l.status IN ('PND', 'RTY') AND l.host_name IS NULL AND l.instance_name IS NULL)
OR (l.status = 'INP' AND l.host_name = i_host_name AND l.instance_name = i_process_name))
AND retry_count < i_retry_count
ORDER BY r.updated_dttm asc, l.created_dttm asc
WHERE
ROWNUM =1)
FOR UPDATE NOWAIT;
EXCEPTION
WHEN lock_detected THEN
NULL;
WHEN NO_DATA_FOUND THEN
NULL;
END;
UPDATE PROCESS_QUEUE
SET status = 'INP',
updated_dttm = sys_extract_utc(current_timestamp),
host_name = i_host_name,
instance_name = i_process_name
WHERE process_id=o_process_id;
COMMIT;
END;
Maybe you are looking for
-
Pscs6 wont open, Microsoft error message
I downloaded the Photoshop CS6 trial verion yesterday and it worked great for afew hours, but I closed it and now every time I try and open it there's an error message "Adobe Photoshop CS6 hs encountered a problem and needs to close" what could have
-
How to create different users in the same iPad 4?
I would like to share my new iPad with other person. How can I create two users.?
-
HT1473 How can I add an album to itunes so it stays as an album?
I have an album. On the album are 12 tracks. The album has already been ripped to my hard drive and lives in a single folder,. When I 'add folder' to itunes, it gives me a convert from WMA message (fine) and starts the transfer. My album arrives in
-
Sample Quiz Application error in resource Bundle
hi sdns , i am stuck with an error. please help me how to rectify this problem. 500 Internal Server Error Web Dynpro Container/SAP J2EE Engine/6.40 Failed to process request. Please contact your system administrator. [Hide] Error Summary While p
-
When I convert to word my doc formIng shifts and font sizes are different. What the problem
Any help with this?