Oracle SKIP LOCKED 是否防止不可重复读取?

Does Oracle SKIP LOCKED prevent non-repeatable reads?

一个事务以 READ COMMITTED 隔离执行这 2 个语句

SELECT * FROM CATS WHERE ID=1 FOR UPDATE SKIP LOCKED
SELECT * FROM CATS WHERE ID=1 

第一个查询 return 是 ID 1 行。我想知道第二个查询是否总是 return 值等于第一个查询的结果?

我的顾虑如下

我已阅读以下问题和相关文章: Force Oracle to return TOP N rows with SKIP LOCKED.

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

这是正确的吗?

如果是,给定 READ COMMITTED 隔离:

我想知道在下面的情况下,T2 是否可以在行被 T1 锁定之前更新行:

  1. T1:Oracle 计算结果集
  2. T2:Oracle更新相同的结果集和COMMIT
  3. T1:Oracle 打开游标
  4. T1:Oracle 对每一行,如果该行已经被锁定则跳过该行

可能吗?

如果 skip locked 成功 returns ID = 1 行后续查询将始终 return 值等于第一个查询的结果。 在 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;