Sql Oracle SKIP LOCKED是否阻止不可重复的读取?
事务使用读提交隔离执行这2条语句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,当光标打开时,结果集将被锁定 这
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
是否可能?如果
跳过锁定
成功返回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,则
将_添加到_结果集(实际_行);
其他的
--数据已更改,请跳过该行
如果结束;
如果结束;
端环;
如果结束;
端环;