真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

變與不變:Undo構(gòu)造一致性讀的例外情況

嘉年華聽(tīng)了恩墨學(xué)院的一個(gè)主題:《重現(xiàn)ORA-01555 細(xì)說(shuō)Oracle 12c Undo數(shù)據(jù)管理》,呂星昊老師介紹了UNDO的概念以及ORA-1555的產(chǎn)生,并介紹了12c以來(lái)Oracle的UNDO相關(guān)的新特性。

你所需要的網(wǎng)站建設(shè)服務(wù),我們均能行業(yè)靠前的水平為你提供.標(biāo)準(zhǔn)是產(chǎn)品質(zhì)量的保證,主要從事網(wǎng)站建設(shè)、成都做網(wǎng)站、企業(yè)網(wǎng)站建設(shè)、手機(jī)網(wǎng)站制作設(shè)計(jì)、網(wǎng)頁(yè)設(shè)計(jì)、成都品牌網(wǎng)站建設(shè)、網(wǎng)頁(yè)制作、做網(wǎng)站、建網(wǎng)站。創(chuàng)新互聯(lián)公司擁有實(shí)力堅(jiān)強(qiáng)的技術(shù)研發(fā)團(tuán)隊(duì)及素養(yǎng)的視覺(jué)設(shè)計(jì)專才。

其中介紹了Oracle如何使用UNDO來(lái)實(shí)現(xiàn)多版本一致性讀,使用了OPEN CURSOR的方式非常巧妙地在很少量數(shù)據(jù)的情況下構(gòu)造出可重現(xiàn)的案例。不過(guò)這個(gè)案例存在一點(diǎn)小的瑕疵,因?yàn)槿绻徊恍⌒?,很可能?huì)導(dǎo)致結(jié)果與預(yù)期不符,這是因?yàn)檫@里有一個(gè)例外存在。

我們先來(lái)模擬一下UNDO構(gòu)造一致性讀的情況,對(duì)于Oracle而言,默認(rèn)的隔離級(jí)別是READ COMMIT,也就是說(shuō)一個(gè)會(huì)話只能看到其他會(huì)話已經(jīng)提交的修改,未提交的修改或者在當(dāng)前會(huì)話查詢發(fā)起之后提交的修改都是不可見(jiàn)的。

再介紹一下OPEN CURSOR,Oracle中當(dāng)一個(gè)游標(biāo)被打開(kāi),其結(jié)果集就已經(jīng)確定了,也就是說(shuō)這個(gè)游標(biāo)會(huì)根據(jù)OPEN CURSOR這個(gè)時(shí)間點(diǎn)對(duì)應(yīng)的SCN來(lái)構(gòu)造一致性查詢。但是OPEN CURSOR時(shí),對(duì)應(yīng)的SQL并不會(huì)被執(zhí)行,在后續(xù)FETCH的時(shí)候(對(duì)于SQLPLUS而言PRINT命令會(huì)觸發(fā)FETCH),SQL才真正被執(zhí)行。使用這種辦法可以模擬一個(gè)大的查詢,OPEN CURSOR相當(dāng)于大的查詢的開(kāi)始時(shí)間,其早于其他會(huì)話的修改提交時(shí)間,而FETCH的時(shí)間相當(dāng)于大查詢讀取到這條記錄的時(shí)間,而該時(shí)間晚于其他會(huì)話提交的時(shí)間:

SQL> SET SQLP 'SQL1> '

SQL1> CREATE TABLE T_UNDO (ID NUMBER, NAME VARCHAR2(30));

Table created.

SQL1> INSERT INTO T_UNDO SELECT ROWNUM, OBJECT_NAME FROM DBA_OBJECTS;

96920 rows created.

SQL1> COMMIT;

Commit complete.

SQL1> CREATE INDEX IND_UNDO_ID ON T_UNDO(ID);         

Index created.

SQL1> SELECT NAME FROM T_UNDO WHERE ID = 1119;

NAME

------------------------------------------------------------

I_EXTERNAL_LOCATION1$

SQL1> VAR C REFCURSOR

SQL1> EXEC OPEN :C FOR SELECT NAME FROM T_UNDO WHERE ID = 1119;

PL/SQL procedure successfully completed.

 在第一個(gè)會(huì)話已經(jīng)構(gòu)造了一個(gè)查詢,下面在會(huì)話2對(duì)這條ID為1119的記錄進(jìn)行修改并提交:

SQL> SET SQLP 'SQL2> '

SQL2> UPDATE T_UNDO SET NAME = 'UPDATED' WHERE ID = 1119;

1 row updated.

SQL2> COMMIT;

Commit complete.

 在會(huì)話3上執(zhí)行查詢,這時(shí)會(huì)看到會(huì)話2修改提交后的結(jié)果:

SQL> SET SQLP 'SQL3> '

SQL3> SELECT NAME FROM T_UNDO WHERE ID = 1119;

NAME

------------------------------------------------------------

UPDATED

 回到會(huì)話1,對(duì)CURSOR變量執(zhí)行PRINT,檢查得到的結(jié)果:

SQL1> PRINT :C  

NAME

------------------------------------------------------------

I_EXTERNAL_LOCATION1$

 到目前為止,所有都是預(yù)期之內(nèi)的結(jié)果,Oracle會(huì)利用UNDO來(lái)存儲(chǔ)UPDATE的前鏡像,當(dāng)查詢發(fā)現(xiàn)需要訪問(wèn)的數(shù)據(jù)塊SCN大于會(huì)話發(fā)起的SCN,而需要通過(guò)UNDO中存儲(chǔ)的前鏡像來(lái)構(gòu)造一致性讀,找到會(huì)話需要讀取的修改前的數(shù)據(jù)。

那么例外來(lái)自哪里呢,在這個(gè)例子中,我們給ID列上創(chuàng)建了一個(gè)索引,如果這不是一個(gè)普通的索引,而是一個(gè)主鍵,那么效果如何呢:

SQL1> DROP INDEX IND_UNDO_ID;

Index dropped.

SQL1> ALTER TABLE T_UNDO ADD PRIMARY KEY (ID);

Table altered.

SQL1> SELECT NAME FROM T_UNDO WHERE ID = 1118;

NAME

------------------------------------------------------------

EXTERNAL_LOCATION$

SQL1> EXEC OPEN :C FOR SELECT NAME FROM T_UNDO WHERE ID = 1118;

PL/SQL procedure successfully completed.

會(huì)話2修改ID為1118的記錄:

SQL2> UPDATE T_UNDO SET NAME = 'UPDATED WITH PK' WHERE ID = 1118;

1 row updated.

SQL2> COMMIT;

Commit complete.

會(huì)話3檢查確認(rèn)修改結(jié)果:

SQL3> SELECT NAME FROM T_UNDO WHERE ID = 1118;

NAME

---------------

UPDATED WITH PK

再次回到會(huì)話1,PRINT游標(biāo)變量:

SQL1> PRINT :C

NAME

------------------------------------------------------------

UPDATED WITH PK

可以看到例外產(chǎn)生了,一致性讀的結(jié)果被破壞了,居然可以查詢到發(fā)生在游標(biāo)打開(kāi)之后提交的修改。

導(dǎo)致這個(gè)例外的原因來(lái)自于一個(gè)隱含函數(shù)_row_cr:

變與不變: Undo構(gòu)造一致性讀的例外情況

 Oracle11g以后,這個(gè)隱含參數(shù)默認(rèn)值修改為T(mén)RUE,這使得Oracle對(duì)于基于主鍵的訪問(wèn)不再采用默認(rèn)的一致性讀方案。當(dāng)然Oracle做出這種修改的目的是為了提高性能,而且僅對(duì)于單行訪問(wèn)生效,而大部分情況下單行訪問(wèn)的效率非常高,因此對(duì)于一致性破壞的影響并不明顯。到18C為止,該參數(shù)仍然為T(mén)RUE。

如果關(guān)閉該參數(shù):

SQL1> ALTER SYSTEM SET "_row_cr" = FALSE;

System altered.

SQL1> SELECT NAME FROM T_UNDO WHERE ID = 1117;

NAME

------------------------------------------------------------

I_EXTERNAL_TAB1$

SQL1> EXEC OPEN :C FOR SELECT NAME FROM T_UNDO WHERE ID = 1117;

PL/SQL procedure successfully completed.

會(huì)話2進(jìn)行修改:

SQL2> UPDATE T_UNDO SET NAME = 'UPDATED NO ROW CR' WHERE ID = 1117;

1 row updated.

SQL2> COMMIT;

Commit complete.

檢查結(jié)果:

SQL3> SELECT NAME FROM T_UNDO WHERE ID = 1117;

NAME

------------------

UPDATED NO ROW CR

回到會(huì)話1檢查結(jié)果:

SQL1> PRINT :C

NAME

------------------------------------------------------------

I_EXTERNAL_TAB1$

Oracle恢復(fù)默認(rèn)的讀一致性隔離級(jí)別。

雖然Oracle認(rèn)為這種優(yōu)化只是針對(duì)主鍵或唯一索引等行級(jí)訪問(wèn)生效,造成數(shù)據(jù)一致性破壞的可能性很小,但是建議對(duì)于一致性要求較高的行業(yè)尤其是金融相關(guān)行業(yè)還是將該特性關(guān)閉,避免因此造成的一致性問(wèn)題。


網(wǎng)站欄目:變與不變:Undo構(gòu)造一致性讀的例外情況
文章源于:http://weahome.cn/article/pcjhej.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部