`
helloman0907
  • 浏览: 28968 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

for update 和 for update nowait 的区别

阅读更多

for update  for update nowait 的区别:

转自:http://www.cnblogs.com/quanweiru/archive/2012/11/09/2762223.html

 

 

 首先一点,如果只是select 的话,Oracle是不会加任何锁的,也就是Oracle select 读到的数据不会有任何限制,虽然这时候有可能另外一个进程正在修改表中的数据,并且修改的结果可能影响到你目前select语句的结果,但是因为没有锁,所以select结果为当前时刻表中记录的状态。

 

 

 如果加入了for update Oracle一旦发现(符合查询条件的)这批数据正在被修改,则不会发出该select语句查询,直到数据被修改结束(被commit),马上自动执行这个select语句。

 

 

 同样,如果该查询语句发出后,有人需要修改这批数据(中的一条或几条),它也必须等到查询结束后(commit)后,才能修改。

 

 

for update nowait for update 都会对所查询到得结果集进行加锁,所不同的是,如果另外一个线程正在修改结果集中的数据,for update nowait 不会进行资源等待,只要发现结果集中有些数据被加锁,立刻返回 ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”。

 

 

for update  for update nowait 加上的是一个行级锁,也就是只有符合where条件的数据被加锁。如果仅仅用update语句来更改数据时,可能会因为加不上锁而没有响应地、莫名其妙地等待,但如果在此之前,for  update NOWAIT语句将要更改的数据试探性地加锁,就可以通过立即返回的错误提示而明白其中的道理,或许这就是For UpdateNOWAIT的意义之所在。

 

 

 经过测试,以for update  for update nowait方式进行查询加锁,在select的结果集中,只要有任何一个记录在加锁,则整个结果集都在等待系统资源(如果是nowait,则抛出相应的异常)

 

 

 

 

 

2for update nowait  for update 的目的: 
锁定表的所有行,排斥其他针对这个表的写操作。确保只有当前事务对指定表进行写操作。 
for update nowait
 for update的区别:

 

 

别的事务要对这个表进行写操作时,是等待一段时间还是马上就被数据库系统拒绝而返回.制定采用nowait方式来进行检索,所以当发现数据被别的session锁定中的时候,就会迅速返回ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源。所以在程序中我们可以采用nowait方式迅速判断当前数据是否被锁定中,如果锁定中的话,就要采取相应的业务措施进行处理。 
如何理解上面的话. 
开启一会话 (就是开一个sqlwindow) 
  select  empno,ename from emp where empno='7369' for update nowait ; 
得到下面结果集: 
    empno  ename 
    7369    smith 
开启另一会话 
  select  empno,ename from emp where empno='7369' for update nowait ; 
返回RA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源 
上面会话都提交commit; 
~~~~~~~~~~~~~~~~~~~~~ 
开启一会话, 
  select  empno,ename from emp where empno='7369' for update ; 
得到下面结果集: 
    empno  ename 
    7369    smith 
开启另一会话 
  select  empno,ename from emp where empno='7369' for update;

阻塞,不返回错误。 
提交第一个会话,第二个回话自动执行 
提交第二个会话 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
   for update: 
当第一个session最后commit或者rollback之后,第二个session中的检索结果就是自动跳出来,并且也把数据锁定住. 
  
开启一会话: 
     select empno,ename from emp   where empno="7369" for update
 
得到下面结果集: 
    empno  ename 
    7369    smith 
开启另一个会话, 
   update emp set ename='ALLEN'  where empno="7396"; 
阻塞。 
  
提交第一个会话,update 语句执行 
再开启一会话 
    update emp set ename="SMITH" where empno='7396'; 
同样阻塞,虽然第一个会话因为提交而释放了锁,但是第二个会话中的update 又给这一行加锁了; 
for update nowait:
当你第一个session放开锁定以后,第二个session才能正常运行。当你第二个session语句运行后,数据又被你第二个session语句锁定住了,这个时候只要你第二个session语句后还没有commit,别的session照样不能对数据进行锁定更新等等。

 

 

对比区别: 
select * from TTable1 for update 锁定表的所有行,只能读不能写 
2  select * from TTable1 where pkid = 1 for update 只锁定pkid=1的行 
3  select * from Table1 a join Table2 b on a.pkid=b.pkid for update 锁定两个表的所有记录 
4 select * from Table1 a join Table2 b on a.pkid=b.pkid where a.pkid = 10 for update 锁定两个表的中满足条件的行 
5. select * from Table1 a join Table2 b on a.pkid=b.pkid where a.pkid = 10 for update of a.pkid 只锁定Table1中满足条件的行 
for update 是把所有的表都锁点 for update of 根据of 后表的条件锁定相对应的表 
----------- 
关于NOWAIT(如果一定要用FOR UPDATE,我更建议加上NOWAIT) 
当有LOCK冲突时会提示错误并结束STATEMENT而不是在那里等待(比如:要查的行已经被其它事务锁了,当前的锁事务与之冲突,加上nowait,当前的事务会结束会提示错误并立即结束 STATEMENT而不再等待). 
如果加了for update后 该语句用来锁定特定的行(如果有where子句,就是满足where条件的那些行)。当这些行被锁定后,其他会话可以选择这些行,但不能更改或删除这些行,直到该语句的事务被commit语句或rollback语句结束为止。 
因为FOR   UPDATE子句获得了锁,所以COMMIT将释放这些锁。当锁释放了,该游标就无效了。 
就是这些区别了 
  
关于oracle中的select...for update of columns 
问题,如下:select * from emp where empno = 7369 for update; 会对表中员工编号为7369的记录进行上锁。其他用户无法对该记录进行操作,只能查询。select * from emp where empno = 7369 for update of sal; 这条语句是不是意味着只对表中的7369 这一行的sal字段的数据进行了上锁,其他数据则可以被其他用户做更新操作呢。学员测试结果为二条语句的效果是一样的。其他用户对整行都无法更新,那么是不是意味着 for update of columns这句没有什么意义呢?

 

 

  这个问题估计很多玩ORACLE的同学们都没有去思考过【网上相关的帖子不多】。现在将其功能讲解一下。

 

 

  从单独一张表的操作来看,上面二条语句的效果确实是相同的。但是如果涉及到多表操作的时候 for update of columns就起到了非常大的作用了。现假定有二个用户,scottmm

 

 

scott执行语句:select * from emp e,dept d where e.deptno = d.deptno for update; --对二张表都进行了整表锁定 
mm
执行语句:select * from scott.dept for update wait 3; --试图锁定scott用户的dept

 

 

结果是: 
ERROR 
位于第 1 : 
ORA-30006: 
资源已被占用; 执行操作时出现 WAIT 超时

 

 

现在,scott用户先进行解锁rollback,再在for update语句后面加上of columns,进行测试

 

 

scott执行语句:select * from emp e,dept d where e.deptno = d.deptno for update of sal ; 
mm
执行语句:select * from scott.dept for update wait 3;

 

 

结果是: 
成功锁定了dept表的数据.

 

 

mm再次执行语句:select * from scott.emp for update wait 3;

 

 

结果是: 
ERROR 
位于第 1 : 
ORA-30006: 
资源已被占用; 执行操作时出现 WAIT 超时

 

 

通过这段代码案例,我们可以得到结论,for update of columns 用在多表连接锁定时,可以指定要锁定的是哪几张表,而如果表中的列没有在for update of 后面出现的话,就意味着这张表其实并没有被锁定,其他用户是可以对这些表的数据进行update操作的。这种情况经常会出现在用户对带有连接查询的视图进行操作场景下。用户只锁定相关表的数据,其他用户仍然可以对视图中其他原始表的数据来进行操作。 
  
Oracle 
for update行锁 
SELECT...FOR UPDATE 语句的语法如下: 
SELECT ... FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED]; 
其中: 
OF 子句用于指定即将更新的列,即锁定行上的特定列。 
WAIT 子句指定等待其他用户释放锁的秒数,防止无限期的等待。 
“使用FOR UPDATE WAIT”子句的优点如下: 
1防止无限期地等待被锁定的行; 
2允许应用程序中对锁的等待时间进行更多的控制。 
3对于交互式应用程序非常有用,因为这些用户不能等待不确定 
4 若使用了skip locked,则可以越过锁定的行,不会报告由wait n 引发的‘资源忙’异常报告

 

 

示例: 
create table t(a varchar2(20),b varchar2(20)); 
insert into t values('1','1'); 
insert into t values('2','2'); 
insert into t values('3','3'); 
insert into t values('4','4'); 
现在执行如下操作: 
plsql develope中打开两个sql窗口, 
1窗口中运行sql 
select * from t where a='1' for update; 
2窗口中运行sql1 
1. select * from t where a='1'; 
这一点问题也没有,因为行级锁不会影响纯粹的select语句 
再运行sql2 
2. select * from t where a='1' for update; 
则这一句sql在执行时,永远处于等待状态,除非窗口1sql被提交或回滚。 
如何才能让sql2不等待或等待指定的时间呢? 我们再运行sql3 
3. select * from t where a='1' for update nowait; 
则在执行此sql时,直接报资源忙的异常。 
若执行 select * from t where a='1' for update wait 6; 则在等待6秒后,报 资源忙的异常。 
如果我们执行sql4 
4. select * from t where a='1' for update nowait skip Locked; 
则执行sql时,即不等待,也不报资源忙异常。 
现在我们看看执行如下操作将会发生什么呢? 
在窗口1中执行: 
select * from t where rownum<=3 nowait skip Locked; 
在窗口2中执行: 
select * from t where rownum<=6 nowait skip Locked; 
select for update 
也就如此了吧,insertupdatedelete操作默认加行级锁,其原理和操作与select for update并无两样。 
select for update of
,这个of子句在牵连到多个表时,具有较大作用,如不使用of指定锁定的表的列,则所有表的相关行均被锁定,若在of中指定了需修改的列,则只有与这些列相关的表的行才会被锁定。

分享到:
评论

相关推荐

    for_update_和_for_update_nowait_的区别

    for_update_和_for_update_nowait_的区别

    oracle中UPDATE nowait 的使用方法介绍

    SQL语句: Sql代码: 代码如下: SELECT * FROM hold_mc_site_product_pic pic WHERE pic.id = 730127 FOR UPDATE nowait 2、应用在多线程并发的情况下。先查询出要处理的数据,并加入数据库级的锁,处理完后,写入...

    Python Sqlalchemy如何实现select for update

    sqlalchemy 对于行级锁有两种实现方式,with_lockmode(self, mode): 和 with_for_update(self, read=False, nowait=False, of=None),前者在sqlalchemy 0.9.0 被废弃,用后者代替。所以我们使用with_for_update ! 看...

    simple-tags

    * Add compatibility with WordPress 2.7, use new API for HTTP and Admin. No new features ! * Version 1.5.7 * Move autolink after ShortCodes * Add Italian and German translation * Fix a potential ...

    SQL Prompt_9.1.15.5260破解版

    SP-7005 : Formatting an UPDATE STATISTICS statement will no longer process out of scope parentheses and cause a "Can't align to a future token 'Update'" crash. SP-7021 : Aliases in quotes no longer ...

    微软内部资料-SQL性能优化3

    For example, suppose a transaction scanned a page using an S lock and then subsequently decided to perform a row level update. The row would obtain an X lock, but now the page would require an IX ...

    EurekaLog_7.5.0.0_Enterprise

    17)..Added: Support for relative file paths and environment variables for events and various module paths 18)..Added: Logging in Manage tool 19)..Added: Windows 10 version detection 20)..Added: Stack ...

    jdbc基础和参考

    save-update:对当前对象执行save,update, saveOrupdate,会级联操作和它相关联的对象 delete:在删除当前对象的时候,级联删除和他相关联的对象 all: save-update+delete delete-orphan:解除关联关系时,删除和当前...

    LCTF软件备份VariSpec™ Liquid Crystal Tunable Filters

    Ideally, one should check VsIsReady() using a timer or the like to wait efficiently, so that the host PC is free to do other tasks while waiting for the VariSpec. The VariSpec always processes each ...

    Turbo C 2.01[DISK]

    Update from TC 1.5 - This allows for an easy update from version 1.5. After the files are copied, all the installed options from your current TC.EXE will be transferred to the new one. This is ...

    Turbo C 2.00[DISK]

    Update from TC 1.5 - This allows for an easy update from version 1.5. After the files are copied, all the installed options from your current TC.EXE will be transferred to the new one. This is ...

    oracle中锁的级别和锁表语句

    文章目录锁模式值列表锁表语句例子wait 和 nowait锁模式row share(share update) 2级锁row exclusive 3级锁share 4级锁share row exclusive 5级锁exclusive 6级锁各个锁的例子其他 锁模式值列表 值为0-6。其实常见的...

    SQL Server死锁总结

    SQL Server死锁总结 ...非剥夺条件(No pre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。 循环等待条件(Circular wait):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。

    Bochs - The cross platform IA-32 (x86) emulator

    - Added support for VGA graphics mode with 400 lines (partial fix for SF bug #2948724) - NE2K: Fixed "send buffer" command issue on big endian hosts - USB - converted common USB code plus devices ...

    CE中文版-启点CE过NP中文.exe

    Symbolhandler: When the symbolhandler now waits till it's done, it won't wait for the structures to be parsed anymore Additions and Changes: Lua Engine: Added autocomplete DLL injection: On DLL ...

    acpi控制笔记本风扇转速

    Disassembler - fix for error emitted for unknown type for target of scope operator. Now, ignore it and continue. Disassembly of an FADT now verifies the input FADT and reports any errors found. Fix ...

    MATLAB GUI

    能量守恒gui_Singleton = 1; gui_State = struct('gui_Name', mfilename, ... 'gui_Singleton', gui_Singleton, ... ...% UIWAIT makes myxiaoqiu wait for user response (see UIRESUME) % uiwait(handles.figure1);

    STG (SNMP Traffic Grapher)

    maximal 2000000000ms (Too long to wait...) To get valid graph this value should be set higher than network timeout. Max Rate - byte/second: minimal 1 maximal 2000000000 This option ...

    让Oracle跑得更快 Oracle 10g性能分析与优化思路.part2.rar

    2.3.1 select for update 30 2.3.2 外键和索引 36 第3章 latch和等待 44 3.1 共享池中的latch争用 45 .3.2 数据缓冲池latch争用 54 3.2.1 表数据块 54 3.2.2 索引数据块 59 3.2.3 索引根数据块 62 3.2.4 段头数据块 ...

Global site tag (gtag.js) - Google Analytics