select ... for update

通常,select ... for update是为了锁定相关的行,保证在查询期间到释放的时候,相关的行集在这个过程中不被其他会话进行写操作(但是其他行集却并无影响)。
比如,有表:
create table t ( id number);
insert into t select object_id from dba_objects where object_id<=100;
commit;
现在t表有100行数据,从1到100;
然后我们在两个会话中进行测试: select ... for update
会话A 会话A执行结果 会话B 会话B执行结果
delete from t where id=2; 执行成功。



select * from t for update; 会话被挂起。
commit; 提交成功。
A会话提交后,B会话执行成功。得到结果集。
update t set id=-1 where  id =10; 会话被挂起。


执行成功。 commit或rollback(这里实际上并无任何数据更改)。 提交成功或回滚成功。
这里,我们看到。当某一行被会话A修改或删除锁定时,如果其他会话执行select for update,就会被挂起。直到会话A提交或回滚,释放了锁。
而当某个会话执行了select ... for update 后,其他会话身体在相关的行集进行写操作(更新或删除),也会被挂起,直到该会话解除锁定。其他会话的写操作才能完成。
那么select ... for update nowait 又有什么区别呢?
接下来测试 : select ... for update nowait
会话A 会话A执行结果 会话B 会话B执行结果
delete from t where id=2; 执行成功。



select * from t for update nowait;
立即返回错误。
第 1 行出现错误:
ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源
commit; 提交成功。
A会话提交后,B会话执行成功。得到结果集。
update t set id=-1 where  id =10; 会话被挂起。


执行成功。 commit或rollback(这里实际上并无任何数据更改)。 提交成功或回滚成功。
通 过两个比的对比发现。当使用 select ...  for update 的时候,如果有相关的行被锁定。那么,查询会被挂起,直到其他会话的锁定被解除。使用select ... for update nowait 的时候,如果有相关行被锁定。不再是挂起,是直接返回一个资源忙的错误。
另外,无论是使用select ... fro update 还是使用 select ... fro update nowait。都会对相关的行集进行锁定,其他会话进行相关行集的写操作都会被挂起,直到该锁定被解除。所以,在使用了select ... fro update或者 select ... fro update nowait 后,要尽快解除锁定,避免其他会话挂起太久。


你可能感兴趣的:(update,insert,number,where,create)