Skip Locked

create table t(id number not null);
insert into t values(1);
insert into t values(2);
insert into t values(3);
commit;

现在连续两次执行同一个SQL语句,如下:
SQL>select * from t where rownum <= 1 for update skip locked;

        ID
----------
         1

1 row selected.

SQL>select * from t where rownum <= 1 for update skip locked;

请问: 这里应该显示什么结果?

A.B.C.D.
no rows selected         ID
----------
         1

1 row selected.
         ID
----------
         2

1 row selected.
         ID
----------
         3

1 row selected.



现在再开启另一个 SESSION窗口执行:
SQL>select * from t where rownum <= 1 for update skip locked;

 

 

1. 我们看看第一个结果, 应该是 B.
这个小知识点地球人都知道, 就是: 同一个SESSION的锁定可以重复获取.

2. 第二题的结果是 A.
我们分析一下为什么出现这个结果,初看感觉是前面的SESSION锁定了全部的记录.
但我们从第二个SESSION 窗口中执行以下语句:
SQL> select * from t for update skip locked;

        ID
----------
         2
         3

2 rows selected.
可以发现后面两条记录并没有被第一个SESSION锁定.
那为何 select * from t where rownum <= 1 for update skip locked; 这个就 no rows 呢?
其实是因为 for update 执行情况我们误解了.
对于存在  for update 的SQL语句, Oracle 首先在没有 For Update 的情况下选取出满足条件的记录.
然后对选取出的记录进行 Lock.  如果后 Skip Locked, 那么在锁定记录的时候对于满足条件的记录中已经被锁定的将会再次被筛选掉.
这就是For update skip locked 的执行过程.

我们第一个SESSION 中锁定了第一条记录(Rownum <=1 ), 第二个SESSION 中依然按照 (Rownum<=1) 取到第一条ID=1的记录,
在后继执行 For Update Skip Locked 的时候发现记录被锁定, 则被筛选掉, 那么最终结果就是 no rows 了.

总结: Skip Locked 是在SQL查询结果集的基础上进行二次筛选.
增加一个由 kmpx 发现的一个知识点: 使用了 For Update 查询的表上会放置一个 MODE=3 的 TM 锁定, 而不管该查询是否查询到数据.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值