Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql Oracle SKIP LOCKED是否阻止不可重复的读取?_Sql_Oracle_Transactions_Isolation Level - Fatal编程技术网

Sql Oracle SKIP LOCKED是否阻止不可重复的读取?

Sql Oracle SKIP LOCKED是否阻止不可重复的读取?,sql,oracle,transactions,isolation-level,Sql,Oracle,Transactions,Isolation Level,事务使用读提交隔离执行这2条语句 SELECT * FROM CATS WHERE ID=1 FOR UPDATE SKIP LOCKED SELECT * FROM CATS WHERE ID=1 第一个查询返回ID1行。我想知道第二个查询是否总是返回与第一个查询结果相等的值 我的担忧如下 我已经阅读了以下问题和相关文章: 如果我理解正确,Oracle首先计算结果集,它打开光标,然后对于每一行,如果该行已被锁定,则跳过该行。如果没有SKIP LOCKED,当光标打开时,结果集将被锁定 这

事务使用读提交隔离执行这2条语句

SELECT * FROM CATS WHERE ID=1 FOR UPDATE SKIP LOCKED
SELECT * FROM CATS WHERE ID=1 
第一个查询返回ID1行。我想知道第二个查询是否总是返回与第一个查询结果相等的值

我的担忧如下

我已经阅读了以下问题和相关文章:

如果我理解正确,Oracle首先计算结果集,它打开光标,然后对于每一行,如果该行已被锁定,则跳过该行。如果没有
SKIP LOCKED
,当光标打开时,结果集将被锁定

这是正确的吗

如果是,给定读提交隔离:

  • 事务
    T1
    执行此语句

    从ID=1的CAT中选择*进行更新跳过锁定

  • 并发事务
    T2
    更新相同的结果集

    更新CATS SET CATS.AGE=10,其中CATS.ID=1

我想知道在下面的场景中,T2是否可以在T1锁定行之前更新该行:

  • T1:Oracle计算结果集
  • T2:Oracle更新相同的结果集并提交
  • T1:Oracle打开光标
  • T1:Oracle对于每一行,如果该行已被锁定,则跳过该行

  • 是否可能?

    如果
    跳过锁定
    成功返回
    ID=1
    行,后续查询将始终返回与第一次查询结果相等的值。 在
    select for update skip locked
    Oracle不首先计算结果集,而是在获取时检查块和行。我将尝试通过编写伪代码来解释它

    start select for update skip locked
    open cursor, skip_locked_SCN := next SCN;
    start fetching
    for block in table_data_blocks loop
      if block.SCN < skip_locked_SCN then  -- unchanged block
        for row in block.rows(where id = :id) loop  -- filter rows
          if row is locked then
            -- skip that row
          else 
            add_to_resultset(row);
          end if;
        end loop;
      else  -- block has been changed
        -- go to undo segment and get previous version
        undo_block := get_from_UNDO(block);  -- (ORA-01555: snapshot too old may be raised)
        for undo_row in undo_block.rows(where id = :id) loop
           actual_row = block.rows(where rowid = undo_row.rowid);  -- get actual version of appropriate row by rowid
           if actual_row is locked then
             -- skip that row
           else
             -- check if data in the row remains unchanged
             if actual_row.data = undo_row.data then
               add_to_resultset(actual_row);
             else
               -- data changed, skip that row
             end if; 
           end if; 
        end loop; 
      end if; 
    end loop;
    
    start选择更新跳过锁定
    打开光标,跳过\u锁定\u SCN:=下一个SCN;
    开始抓取
    对于表\u数据\u块循环中的块
    如果block.SCN<跳过\u锁定\u SCN,则--未更改的块
    对于block.rows(其中id=:id)循环中的行--筛选行
    如果行被锁定,则
    --跳过那一排
    其他的
    将_添加到_结果集(行);
    如果结束;
    端环;
    否则--块已更改
    --转到“撤消段”并获取以前的版本
    undo_block:=从_undo(block)中获取_;--(ORA-01555:可能引发快照太旧)
    对于undo_block.rows(其中id=:id)循环中的undo_行
    实际_row=block.rows(其中rowid=undo_row.rowid);--按rowid获取相应行的实际版本
    如果实际_行被锁定,则
    --跳过那一排
    其他的
    --检查行中的数据是否保持不变
    如果实际_row.data=撤消_row.data,则
    将_添加到_结果集(实际_行);
    其他的
    --数据已更改,请跳过该行
    如果结束;
    如果结束;
    端环;
    如果结束;
    端环;