oracle--select for update nowait 与 select for update 区别

nowait的含义很多人都会误解为“不用等待,立即执行”。但实际上该关键字的含义是“不用等待,立即返回”
如果当前请求的资源被其他会话锁定时,会发生阻塞,nowait可以避免这一阻塞,因为
If another user is in the process of modifying that row, we will get an ORA‐00054
Resource Busy error. We are blocked and must wait for the other user to finish with
it.
可以实验下,我用pl/sql developer锁定表game
SQL> select * from game where game_id =1;
返回一条记录

SQL> select * from game where game_id=1 for update nowait;
select * from game where game_id=1 for update nowait
*
ERROR位于第1行:
ORA-00054:资源正忙,要求指定NOWAIT
使用NOWAIT关键字,会报ORA‐00054的错误


如何来查看是什么资源造成这样的情况呢?并且怎么解决呢?
查看锁定的对象,用户和会话
SQL> select lo.oracle_username,do.object_name,s.logon_time,lo.process,s.sid as s
ession_id
2 from v$locked_object lo,v$session s,dba_objects do
3 where lo.session_id = s.sid and do.object_id = lo.OBJECT_ID
4 /
ORACLE_USERNAME
------------------------------
OBJECT_NAME
--------------------------------------------------------------------------------
LOGON_TIME PROCESS SESSION_ID
------------------- ------------ ----------
NBA---用户名称
GAME---操作的对象
2009-08-04 10:55:15---登录的时间 840:5176 10


使用as sysdba
根据sid查看具体的sql语句
selectsql_textfromv$session a,v$sqltext_with_newlines b
whereDECODE(a.sql_hash_value,0, prev_hash_value, sql_hash_value)=b.hash_value
anda.sid=10;
begin :id := sys.dbms_transaction.local_transaction_id; end;

kill session
SQL> select sid,serial# from v$session where sid =10;

SID SERIAL#
---------- ----------
10 23
SQL> alter system kill session '10,23';

系统已更改。

select * from game where game_id=1 for update nowait;
有数据返回了

当两个用户同时更新同一条记录是, 使用select for update,后执行者,会被阻塞,而使用select for update nowait 则会抛出:ORA-00054 resource busy and acquire with NOWAIT specified 异常,告之用户这一行已经锁定。

原文来源:[url]http://www.blogjava.net/parable-myth/archive/2010/11/05/337350.html?opt=admin[/url]
根据提供的引用内容,select for update是一种在Oracle数据库中使用的锁定机制,它可以锁定符合where条件的数据行,以防止其他事务对这些数据行进行修改。而select for update nowait则是在锁定数据行时,如果无法立即获取锁定,则会立即返回错误信息,而不是等待其他事务释放锁定。 相比之下,select for update insteal是一种更加灵活的锁定机制,它可以在不阻塞其他事务的情况下锁定数据行。当一个事务需要锁定某些数据行时,如果这些数据行没有被其他事务锁定,则该事务可以立即获取锁定并继续执行。如果这些数据行已经被其他事务锁定,则该事务会等待其他事务释放锁定,然后再获取锁定并继续执行。 以下是一个使用select for update insteal的示例: ```sql -- 假设有一个名为test的表,其中包含id和name两列 -- 现在需要锁定id为1的数据行,以便进行修改操作 -- 如果该数据行已经被其他事务锁定,则等待其他事务释放锁定后再进行锁定操作 -- 开启一个事务 BEGIN TRANSACTION; -- 锁定id为1的数据行 SELECT * FROM test WHERE id = 1 FOR UPDATE OF name NOWAIT; -- 如果上一条语句返回了错误信息,则表示无法立即获取锁定 -- 可以选择等待一段时间后再次尝试获取锁定,或者回滚事务并退出 -- 如果上一条语句没有返回错误信息,则表示已经成功获取锁定 -- 可以对该数据行进行修改操作 -- 提交事务 COMMIT; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值