oracle小知識點2--一致性讀中的重啟動更新

selectshen發表於2015-06-19
以下三個問題,個人覺得很有趣,如果沒有了解oracle的重啟動更新,可能會對查詢結果感到懷疑~
--oracle version:11.2.0.2.0
--問題一:
----建測試表
create table scott.test01
as select 1 a from dual
union all select 2 from dual
union all select 3 from dual;
----查詢結果
select * from scott.test01;
/*
A
1
2
3
*/

----session 1執行:
update scott.test01
set a=3
where a<3;

----session 2執行:
update scott.test01
set a=2
where a=3;

----session 1執行:
commit;

----session 2執行:
commit;

----session 1執行:
select * from scott.test01;
----此處session 1的查詢結果是
/*
3
3
2
*/
問題一的結果,說明session 1的update沒有影響到session 2的update
session 1 update後,根據一致性讀,session 2看到的還是沒有更新過的結果.session 2做update操作鎖定的行與session 1 update時鎖定的行不相同.
session 1 commit提交要更新的行,並釋放鎖,session 2 commit提交要更新的行,並釋放鎖,相互之間不影響.

--問題二:
----建測試表
drop table scott.test01 purge;

create table scott.test01
as select 1 a from dual
union all select 2 from dual
union all select 3 from dual;

----查詢結果
select * from scott.test01;
/*
A
1
2
3
*/

----session 1執行:
update scott.test01
set a=1
where a>1;

----session 2執行:
update scott.test01
set a=4
where a<3;

----session 1執行:
commit;

----session 2執行:
commit;
----session 1執行:
select * from scott.test01;
----此處session 1的查詢結果是什麼?
/*
4
4
4
*/
問題二的結果,說明session 1的update影響到session 2的update
session 1 update後,根據一致性讀,session 2看到的還是沒有更新過的結果.session 2做update操作鎖定行時,與session 1 update時鎖定的行在a=2這一行是相同的,此時session 2會被阻塞,等待session 1 commit或rollback.
session 1 commit提交要更新的行,並釋放鎖.
重點來了,由於session 1提交後,session 2要鎖定的行對應的where a<3中a的值有變更,此時oralce內部會回滾更新,並重啟動更新,因為原本a=3被session 1更新為a=1,所以在重啟動
更新時也會被where a<3所包含,最後三條記錄全部被更新了.

--問題三:
----建測試表
drop table scott.test01 purge;

create table scott.test01
as select 1 a from dual
union all select 2 from dual
union all select 3 from dual;
----查詢結果
select * from scott.test01;
/*
A
1
2
3
*/

----session 1執行:
update scott.test01
set a=2
where a>1;

----session 2執行:
update scott.test01
set a=4
where a<3;

----session 1執行:
commit;

----session 2執行:
commit;
----session 1:
select * from scott.test01;
----此處session 1的查詢結果是什麼?
/*
4
4
2
*/
問題三的結果,說明session 1的update沒有影響到session 2的update
session 1 update後,根據一致性讀,session 2看到的還是沒有更新過的結果.session 2做update操作鎖定行時,與session 1 update時鎖定的行在a=2這一行是相同的,此時session 2會被阻塞,等待session 1 commit或rollback.
session 1 commit提交要更新的行,並釋放鎖.
由於session 1提交後,session 2要鎖定的行對應的where a<3中a有更新,但a=2的值沒有變更,此時oralce不需要回滾更新,所以更新之前鎖定的兩行,原本a=3的行雖然在session 1中已經被更新為2滿足where a<3,但由於沒有重啟動更新,就不會更新這一行.

--備註:
這樣看來,重啟動更新 依賴於會話之間的行鎖阻塞及where條件中的值變更.在計算結果的時候,要結合rowid和where條件一起比較容易判斷.重啟動更新可以透過觸發器撲捉到.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28539951/viewspace-1705502/,如需轉載,請註明出處,否則將追究法律責任。

相關文章