您的位置:首页 > 大数据 > 人工智能

for update 和 for update nowait 的区别

2013-12-06 22:13 323 查看
for update 和 for update nowait 的区别

如果在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 Update和NOWAIT的意义之所在。

for update 和 for update nowait如果对应的select语句有where条件时,只会锁住对应的where条件下的数据,而不会锁住整张表中的所有数据。

在编写程序中,如果涉及到对表进行update,一定要对该表进行锁定,否则将出现死锁情况。

example:

当执行如下语句未进行commit时:SELECT * FROM cux_test t WHERE t.process_status = 'PENDING' FOR UPDATE NOWAIT;

同时再执行对应的如下程序,会报资源正忙的错误:

DECLARE

  CURSOR cur_lock IS

    SELECT *

      FROM cux_test t

     WHERE t.process_status = 'PENDING'

       FOR UPDATE NOWAIT;

BEGIN

  --check lock table

  OPEN cur_lock;

  dbms_output.put_line('IN CURSOR cur_lock');

  IF cur_lock%NOTFOUND THEN

    CLOSE cur_lock;

  END IF;

  CLOSE cur_lock;

 

  --update table

  UPDATE cux_test c

     SET c.process_group_id = 1

   WHERE c.process_status = 'SKIP';

  dbms_output.put_line('update table1 success');

EXCEPTION

  WHEN OTHERS THEN

    dbms_output.put_line('error');

    dbms_output.put_line('other error' || SQLERRM);

END;

而当我们另外执行对应的process_status不是PENDING的for update nowait语句时不会报任何错:

DECLARE

  CURSOR cur_err_lock IS

    SELECT *

      FROM cux_test t

     WHERE t.process_status = 'SKIP'

       FOR UPDATE NOWAIT;

BEGIN

  --check lock table

  OPEN cur_err_lock;

  dbms_output.put_line('IN CURSOR cur_err_lock');

  IF cur_err_lock%NOTFOUND THEN

    CLOSE cur_err_lock;

  END IF;

  CLOSE cur_err_lock;

 

  --update table

  UPDATE cux_test c

     SET c.process_group_id = 2

   WHERE c.process_status = 'SKIP';

  dbms_output.put_line('update table2 success');

EXCEPTION

  WHEN OTHERS THEN

    dbms_output.put_line('error');

    dbms_output.put_line('other error' || SQLERRM);

END;

这里需要注意的是for update和for update nowait语句在同一session中只要使用一次就能锁住对应表的对应记录直到该session结束,意思是在一个session中如果对一张表update多次时只要进行一次lock的检查。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息