总结:

select for update 可以看成 select for update wait UN-LIMITED——查询记录如果被锁,则等待释放。执行过程中"自己"也会上行级锁,直到事务提交select for update wait X—— 对某个记录进行查询,如果有被锁,则等待X秒。同样执行过程会上锁。select for update nowait —— 对某个记录进行查询,如果有被锁,则直接报错。

转载自(原文错误的地方,这里已标红修改):select for update和select for update wait和select for update nowait的区别 - 郑小超 - 博客园https://www.cnblogs.com/GreenLeaves/p/6576646.html

CREATE TABLE "TEST6"
(    "ID" VARCHAR2(30), "NAME" VARCHAR2(30), "AGE" NUMBER(2,0), "SEX" VARCHAR2(2), "ENAME" VARCHAR2(30), "ADDTIME" DATE
)
insert into TEST6 (id, name, age, sex, ename, addtime) values ('1', '张三', 18, null, 'zhangsan', to_date('14-03-2017 00:00:09', 'dd-mm-yyyy hh24:mi:ss'));
insert into TEST6 (id, name, age, sex, ename, addtime) values ('2', '李四', null, '1', 'Lisi', to_date('01-03-2017 02:00:00', 'dd-mm-yyyy hh24:mi:ss'));
insert into TEST6 (id, name, age, sex, ename, addtime) values ('3', '王五', 20, '0', 'wangwu', to_date('09-01-2017 08:55:00', 'dd-mm-yyyy hh24:mi:ss'));
insert into TEST6 (id, name, age, sex, ename, addtime) values ('4', '赵六', 23, '0', 'zhaoliu', to_date('03-03-2016 04:00:00', 'dd-mm-yyyy hh24:mi:ss'));
insert into TEST6 (id, name, age, sex, ename, addtime) values ('5', '冯七', 22, null, 'fengqi', to_date('08-03-2017 12:00:01', 'dd-mm-yyyy hh24:mi:ss'));
CREATE TABLE "TEST8"
(    "ID" NUMBER, "ORDERID" NUMBER, "PRODUCTID" NUMBER, "PRICE" NUMBER(10,2), "QUANTITY" NUMBER
)
insert into TEST8 (id, orderid, productid, price, quantity) values (1, 1, 1, 6, 10);
insert into TEST8 (id, orderid, productid, price, quantity) values (2, 1, 2, 4, 5);
insert into TEST8 (id, orderid, productid, price, quantity) values (3, 1, 3, 10, 2);
insert into TEST8 (id, orderid, productid, price, quantity) values (4, 2, 1, 3, 6);
insert into TEST8 (id, orderid, productid, price, quantity) values (5, 2, 2, 4, 6);

以上是基础数据

在oracle中,如果只进行select语句的话,是不会进行加锁的,也就是oracle会返回当前时刻的结果集,即使这个时候可能有另外一个进程在修改当前结果集的数据,因为没有加锁,所以oracle还是会正常的返回当前时刻的结果集,不会有任何影响。

他们三个共同点:

当使用select for update 或者select for update wait或者.....,那么oralce会给符合where条件的数据行加上一个行级锁

1、select for update

但是如果你的select 语句加了for update,那么就不是上面这回事了,当oracle发现select的当前结果集中的一条或多条正在被修改(注意:当数据被修改时,此时的数据行是被加锁的),那么他就会等到当前当前结果集被修改完毕并且commit之后才进行select操作,并对结果集进行加锁。同样的,如果查询语句发出后,其他会话需要修改结果集中的一条(或几条数据)也许要等到查询结束(commit)之后,才可以执行修改操作。

代码如下:

新建SQL窗口1,(相当于新建一个session会话)

select * from test8 for update

for  update 对整个结果集进行了加锁,意味着在当前session进行commit之前,任何其他的session进行update、delete、select for update操作都会进行等待。

注意:Oracle中insert 是可以执行的,Oracle的隔离级别是读已提交,是存在幻读的。

新建SQL窗口2(相当于新建一个session会话)

update test8 set price=6 where ID=1

显示执行中,等待会话一的查询执行完成

现在我们将会话一的事务提交(commit)

会话二的update语句执行成功

2、select for update nowait

for  update和for update nowait都会对查询到的当前结果集进行加锁,所不同的是,当有另外的会话在修改当前结果集中的数据,select for nowait所进行的查询操作不会进行等待,当发现结果集中的一些数据被加锁,立刻返回 “ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”。测试代码如下:

新建一个SQL窗口1(相当于新建一个会话)

update test8 set price=3 where ID=1

更新test8表的一条数据,但是不进行commit操作

然后新建SQL窗口2(相当于新建一个会话)select for update nowait操作

select * from test8 for update nowait

总结分析:

因为会话一,并没有commit所以test8中的ID=1的行被加锁了,所以当会话二进行select for update nowait检索到ID=1的数据行被加锁了,就立刻返回 “ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”的错误。

接下来我们对会话一进行commit操作,

在执行会话二的select查询,ok,可以查出来了,并且对当前数据集进行了加锁操作,其他会话想要进行修改操作,必须等到会话二commit之后

3、select for update wait

它也会对查询到的结果集进行加锁,select for update wait与select for update nowait不同的地方是,当有另外的会话对它的查询结果集中的某一行数据进行了加锁,那么它不会像nowait一样,立即返回"ORA-00054错误",而是它支持一个参数,设定等待的时间,当超过了设定的时间,那一行数据还处于加锁的状态,那么它也会返回“ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”。测试代码如下:

首先新建SQL窗口1(相当于新建一个会话)执行update 语句,但是不进行commit操作,那么当前数据行将被lock

update test8 set price=3 where ID=1

接着新建SQL窗口2(相当于新建一个会话),在执行select for update wait 6,如果当前查询检索的数据集中,有被加锁了的行数据,那么等待6秒,如果6秒后,其他会话,还没有执行commit释放被加了锁的数据行的话,那么返回“ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源”。

select * from test8 for update wait 6

执行语句6秒后,报错。

最后对会话一(SQL窗口一)进行commit操作

紧接着执行会话二(SQL窗口二)中的sql语句,此时被加锁的数据行被释放

正常的检索除了数据行,当时当前数据集被加锁,其他会话想操作此数据集,必须等会话二中的事务commit之后,才可以进行修改

4、OF子句

在多表查询中如果需要对多表查询的结果集进行加锁,可以使用OF子句。

如果存在OF子句,那么就对满足OF子句的单表进行加锁,如果不存在OF子句就对整个结果集进行加锁,代码如下:

a、不使用OF子句

select a.ID,a.Name,b.price from test6 a
LEFT JOIN test8 b
ON a.ID=b.ID where b.ID>3
for update

没有进行commit操作,此时对test6和test8中的ID>3的数据行都进行了加锁,测试代码如下:

新建一个会话,执行以下语句:

select * from test6 for update skip locked

select * from test8 for update skip locked

测试结果证明,在没有OF子句的情况下,对多表查询的结果集进行select foe update,oracle会对满足where 条件的所有数据行进行加锁

b、使用OF子句

使用OF子句,那么oracle就会对满足OF子句的表进行加锁,在多表查询中。代码如下:

select a.ID,a.Name,b.price from test6 a
LEFT JOIN test8 b
ON a.ID=b.ID where b.ID>3
for update of a.ID

在不执行commit操作的情况,新建一个会话,执行一下语句:

select * from test6 for update skip locked

select * from test8 for update skip locked

比对测试结果,发现在OF子句的作用下,oracle对同时满足where子句(设置要加锁的数据行)和OF子句(主要设置加锁的表)的数据行进行了加锁。

oracle for update wait 解析相关推荐

  1. 资源放送丨《 先睹为快!Oracle 20c新特性解析》PPT视频

    前段时间,墨天轮邀请到了云和恩墨CTO.ACDU核心专家."Oracle百科全书" 杨廷琨 老师分享<先睹为快!Oracle 20c新特性解析>,在这里我们共享一下PP ...

  2. 【亲测有效】Ubuntu18.04 sudo apt update无法解析域名的解决方案

    [亲测有效]Ubuntu18.04 sudo apt update无法解析域名的解决方案 参考文章: (1)[亲测有效]Ubuntu18.04 sudo apt update无法解析域名的解决方案 ( ...

  3. oracle中nowait怎么用,oracle中UPDATE nowait 的使用方法介绍

    oracle中UPDATE nowait 的使用方法介绍 1.UPDATE nowait 应用以下场景:查询某条数据,并对其开启数据库事务.如果查询的当前数据没有加锁,则正确返回结果,并对当前数据加锁 ...

  4. oracle INS-40930,Oracle 并行原理深入解析及案例精粹

    Oracle 并行原理深入解析及案例精粹 [日期:2012-08-12] 来源:Linux社区 作者:Leonarding [字体:大 中 小] (12)sqlload直接加载对索引的影响 所谓对索引 ...

  5. oracle回退的办法,【案例】Oracle for update回退导致业务阻塞的解决办法

    [案例]Oracle for update回退导致业务阻塞的解决办法 时间:2016-11-02 20:53   来源:Oracle研究中心   作者:HTZ   点击: 次 天萃荷净 Oracle研 ...

  6. oracle中next_day()函数解析

    oracle中next_day()函数解析 Sql代码 当前系统时间的下一星期一的时间select   next_day(sysdate,1) from dual NEXT_DAY(date,char ...

  7. oracle千万行update优化,Oracle的update优化

    Oracle的update语句优化研究 一. update语句的语法与原理 1. 语法 单表:UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值如:update t_join ...

  8. oracle执行update语句卡死

    oracle执行update语句卡死 问题:当在plsql上执行update语句时,一直在显示正在执行中,很久不出结果.执行select语句或者是其他表的update语句时,可以正常执行 原因:只有u ...

  9. java中oracle.链接,java连接Oracle数据库的方法解析

    本文主要对java连接Oracle数据库方法进行步骤解析,具有很好的参考价值,需要的朋友一起来看下吧 Oracle数据库先创建一个表和添加一些数据 1.先在Oracle数据库中创建一个student表 ...

最新文章

  1. [译] iOS 开发之新版 APNs 搭建必备知识
  2. vscode怎么弄php,vscode如何设置语言
  3. PHP与C sharp互解加密算法
  4. 第二天:Swift手势操控弹性按钮
  5. CSS结构的基础认知
  6. mysql硬盘备份_原创-在mysql中把里面的数据库备份到自己的硬盘上
  7. 17.1 Replication Configuration 复制:
  8. 木兰宽松许可证(MulanPSL v2)解析
  9. Ubantu16.04+CUDA10.0安装mmaction以及提取UCF101的frame和optical flow
  10. android 4.4 zygote 开机速度,一种安卓系统快速开机的方法及装置的制造方法
  11. 【已开源】Flutter 穿山甲广告插件的集成-FlutterAds
  12. 网站的中英文切换--i18next
  13. 36页智慧安防小区管控系统解决方案
  14. CSS控制文本超出打点显示
  15. 马仕健原创的“光盘行动之歌”《粒粒皆辛苦》在网络走红
  16. 贩妖记 第六十六章,水底大鱼
  17. harmonyos开源,华为杨海松:鸿蒙系统支持第三方手机 “开源开放毫无保留”
  18. text-justify属于css3,css3 text-justify属性怎么用
  19. Python数据转换-有符号短整型转换无符号短整型
  20. 51单片机简单的驱动LCD1602

热门文章

  1. 笔记36 笨办法学python练习43面向对象OOP的文字理解(一)
  2. 写一个matlab程序,自己写的第一个matlab程序
  3. Ajax 应用的思考
  4. 未来计算机游戏,未来可追 ROG光刃G15游戏电脑首发登场
  5. Fedora安装 win7 32b 安装fedora x64 dvd
  6. Thinkphp 5.0 购物网站
  7. cbnet环境配置和运行中遇到的问题
  8. ueditor编辑器对接米秀
  9. 爬虫实现百度贴吧的图片爬取
  10. 自然数与有理数的双射函数