sql – Oracle选择更新行为
我们试图解决的问题看起来像这样.
>我们有一张充满行代表桌子的桌子.预约交易的目的是将卡分配给客户端 我们的解决方案是为卡分配状态,并存储它的预约日期.在预订卡时,我们使用“select for update”语句来执行该卡.该查询查找可用的卡片和很久以前保留的卡片. 但是我们的查询无法正常工作. 我已经准备了一个简化的情况来解释这个问题. -- first,in session 1 set autocommit off; select id from card_numbers where id is not null and rownum <= 1 for update skip locked; 我们不在这里提交交易,该行必须被锁定. -- later,in session 2 set autocommit off; select id from card_numbers where id is not null and rownum <= 1 for update skip locked; 预期的行为是在两个会话中,我们得到一个满足查询条件的单独的不同行. 但是它不会这样工作.根据我们是否使用查询的“跳过锁定”部分,而不是行为变化: >没有“跳过锁定” – 第二个会话被阻止 – 等待会话中的事务提交或回滚 所以,在这个漫长的介绍之后出现的问题. 在Oracle中可以使用所需的锁定方式吗?如果是,那我们做错了什么?什么是正确的解决方案? 解决方法对于FOR UPDATE SKIP LOCKED遇到的行为已在 this blog note中进行了描述.我的理解是,在WHERE子句之后对FOR UPDATE子句进行了评估. SKIP LOCKED就像一个额外的过滤器,保证在返回的行中没有一个被锁定.您的语句在逻辑上相当于:从card_numbers找到第一行,如果没有锁定则返回.显然这不是你想要的. 这是一个重复你所描述的行为的小测试用例: SQL> CREATE TABLE t (ID PRIMARY KEY) 2 AS SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 1000; Table created SESSION1> select id from t where rownum <= 1 for update skip locked; ID ---------- 1 SESSION2> select id from t where rownum <= 1 for update skip locked; ID ---------- 没有从第二个选择返回行.您可以使用光标来解决此问题: SQL> CREATE FUNCTION get_and_lock RETURN NUMBER IS 2 CURSOR c IS SELECT ID FROM t FOR UPDATE SKIP LOCKED; 3 l_id NUMBER; 4 BEGIN 5 OPEN c; 6 FETCH c INTO l_id; 7 CLOSE c; 8 RETURN l_id; 9 END; 10 / Function created SESSION1> variable x number; SESSION1> exec :x := get_and_lock; PL/SQL procedure successfully completed x --------- 1 SESSION2> variable x number; SESSION2> exec :x := get_and_lock; PL/SQL procedure successfully completed x --------- 2 由于我明确地获取了游标,所以只会返回一行(只有一行被锁定). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |