溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Oracle Cursor的相關(guān)知識(shí)點(diǎn)有哪些

發(fā)布時(shí)間:2021-11-09 14:10:38 來(lái)源:億速云 閱讀:135 作者:iii 欄目:關(guān)系型數(shù)據(jù)庫(kù)

本篇內(nèi)容介紹了“Oracle Cursor的相關(guān)知識(shí)點(diǎn)有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

游標(biāo)是一個(gè)基本對(duì)象,它是SQL語(yǔ)句或PL/SQL編程式構(gòu)造的一種完整可執(zhí)行表示,可以被任何授權(quán)會(huì)話使用和重用。游標(biāo)必須被創(chuàng)建,定位(通過(guò)搜索來(lái)查找),消毀(回收),失效與重載。如果游標(biāo)的任何部分不在共享池中,并且出于任何原因需要,則必須重新加載該游標(biāo),這會(huì)降低性能。

開(kāi)發(fā)人員通常對(duì)游標(biāo)有很好的理解因?yàn)樗麄冃枰獙iT創(chuàng)建,打開(kāi),執(zhí)行,獲取與關(guān)閉游標(biāo)。DBA通常將游標(biāo)作為與SQL相關(guān)的簡(jiǎn)單內(nèi)存塊來(lái)看待。然而,這種過(guò)于簡(jiǎn)單的關(guān)點(diǎn)限制了我們?yōu)榕c游標(biāo)相關(guān)的性能問(wèn)題創(chuàng)建解決方案的能力。因此,如果花時(shí)間更好地理解游標(biāo),將會(huì)注意到性能解決方案選項(xiàng)將顯著增加。

父游標(biāo)與子游標(biāo)
游標(biāo)這個(gè)術(shù)語(yǔ)本身是一個(gè)抽象概念,用來(lái)引用共享的信息(位于共享SQL區(qū)),私有信息(位于會(huì)話的PGA)與用來(lái)定位各種游標(biāo)組件的library cache chain節(jié)點(diǎn)(當(dāng)引用library cache時(shí)就叫作handle)。不幸地是這種多用途的定義也增加了混淆。當(dāng)一個(gè)游標(biāo)被關(guān)閉時(shí),Oracle不會(huì)簡(jiǎn)單的回收這三個(gè)游標(biāo)組件。而是Oracle可能會(huì)按需來(lái)回收游標(biāo)組件。

一個(gè)游標(biāo)第一次執(zhí)行時(shí),會(huì)存在一個(gè)父游標(biāo)與子游標(biāo)。后續(xù)的會(huì)話,即使相同的會(huì)話執(zhí)行相同的SQL語(yǔ)句(哈希值相同),可能會(huì)使用不同的子游標(biāo)。雖然SQL語(yǔ)句在文本上完全相同,但是創(chuàng)建子游標(biāo)是為了捕獲特定的特征,比如優(yōu)化模式的差異(例如first_rows),這會(huì)導(dǎo)致不同的執(zhí)行計(jì)劃或不同的會(huì)話級(jí)參數(shù)(cursor_sharing=similar)。下面的例子簡(jiǎn)單的顯示了相同會(huì)話執(zhí)行相同SQL語(yǔ)句兩次,只是在兩次執(zhí)行之間執(zhí)行了alter session命令,這足以強(qiáng)制創(chuàng)建一個(gè)額外的子游標(biāo)。trace命令用來(lái)證明創(chuàng)建了兩個(gè)子游標(biāo)。

SQL> oradebug setmypid
Statement processed.
SQL> alter session set optimizer_mode = all_rows;
Session altered.
SQL> select * from dual;
D
-
X
SQL> alter session set optimizer_mode = first_rows;
Session altered.
SQL> select * from dual;
D
-
X
SQL> alter session set events 'immediate trace name library_cache level 10';
Session altered.
SQL> oradebug tracefile_name
/u01/app/oracle/diag/rdbms/jy/jy1/trace/jy1_ora_6675.trc

下面的內(nèi)容是上面的trace命令所創(chuàng)建的跟蹤文件中的一部分內(nèi)容。我們通過(guò)搜索select * from dual來(lái)定位我們關(guān)心的內(nèi)容并檢查SQL語(yǔ)句。此時(shí),我們感興趣的是,這條SQL語(yǔ)句僅由一個(gè)會(huì)話執(zhí)行,但它創(chuàng)建了兩個(gè)子游標(biāo)。

Bucket: #=108289 Mutex=0xc5eeae00(3298534883328, 1118, 0, 6)
  LibraryHandle:  Address=0xcf2e9a48 Hash=382da701 LockMode=0 PinMode=0 LoadLockMode=0 Status=VALD
    ObjectName:  Name=select * from dual
      FullHashValue=0d54fc02b2ad4044a2cb0974382da701 Namespace=SQL AREA(00) Type=CURSOR(00) ContainerId=1 ContainerUid=1 Identifier=942515969 OwnerIdn=0
    Statistics:  InvalidationCount=0 ExecutionCount=2 LoadCount=3 ActiveLocks=0 TotalLockCount=2 TotalPinCount=1
    Counters:  BrokenCount=1 RevocablePointer=1 KeepDependency=2 Version=0 BucketInUse=1 HandleInUse=1 HandleReferenceCount=0
    Concurrency:  DependencyMutex=0xcf2e9af8(0, 2, 0, 0) Mutex=0xcf2e9b98(768, 37, 0, 6)
    Flags=RON/PIN/TIM/PN0/DBN/[10012841] Flags2=[0000]
    WaitersLists:
      Lock=0xcf2e9ad8[0xcf2e9ad8,0xcf2e9ad8]
      Pin=0xcf2e9ab8[0xcf2e9ab8,0xcf2e9ab8]
      LoadLock=0xcf2e9b30[0xcf2e9b30,0xcf2e9b30]
    Timestamp:  Current=04-17-2019 09:33:16
    HandleReference:  Address=0xcf2e9c20 Handle=(nil) Flags=[00]
    ReferenceList:
      Reference:  Address=0x84497a08 Handle=0x818e2850 Flags=ROD[21]
      Reference:  Address=0x84c9e3d0 Handle=0xb28b76a0 Flags=ROD[21]
    LibraryObject:  Address=0xbd5972a8 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
      DataBlocks:
        Block:  #='0' name=KGLH0^382da701 pins=0 Change=NONE
          Heap=0x83043cc0 Pointer=0xbd597378 Extent=0xbd597200 Flags=I/-/P/A/-/-/-
          FreedLocation=0 Alloc=3.390625 Size=3.976562 LoadTime=4111958371
      ChildTable:  size='16'
        Child:  id='0' Table=0xbd598128 Reference=0xbd597bf8 Handle=0xb38e2928
        Child:  id='1' Table=0xbd598128 Reference=0xbd597f48 Handle=0xbdfc20a8
    NamespaceDump:
      Parent Cursor:  sql_id=a5ks9fhw2v9s1 parent=0xbd597378 maxchild=2 plk=n ppn=n prsfcnt=0 obscnt=0
        CursorDiagnosticsNodes:
          ChildNode:  ChildNumber=0 ID=3 reason=Optimizer mismatch(10) size=3x4 optimizer_mode_hinted_cursor=0 optimizer_mode_cursor=1 optimizer_mode_current=2

庫(kù)緩存對(duì)象之間的關(guān)系不僅為執(zhí)行目的而必須維護(hù),而且當(dāng)其中一個(gè)組件發(fā)生更改時(shí)也必須維護(hù)。假設(shè)一個(gè)表被2000個(gè)SQL語(yǔ)句,100個(gè)函數(shù)與20個(gè)包所引用。現(xiàn)在假設(shè)表的一列被重命名。Oracle將會(huì)使所有相關(guān)的SQL語(yǔ)句與程序結(jié)構(gòu)失效。這可能導(dǎo)致在請(qǐng)求latching與locking時(shí)出現(xiàn)級(jí)聯(lián)效應(yīng)。多個(gè)相關(guān)會(huì)話、失效、重新編譯和計(jì)時(shí)的組合導(dǎo)致整個(gè)Oracle實(shí)例被鎖定。很明顯Oracle已經(jīng)知道了這種問(wèn)題的嚴(yán)重性并且積極的減小出現(xiàn)這種情況的可能性。但每個(gè)DBA要了解library cache之間的關(guān)系是非常復(fù)雜的并且有時(shí)可能導(dǎo)致出現(xiàn)問(wèn)題。

Cursor Building
當(dāng)在library cache中搜索并沒(méi)有找到游標(biāo)時(shí)就會(huì)創(chuàng)建游標(biāo)。這就是硬解析。很明顯這是一個(gè)相對(duì)昂貴的操作它需要請(qǐng)求內(nèi)存管理(分配與可能回收),使用latching來(lái)確保序列化,使用locking來(lái)阻止不合適的更改,執(zhí)行內(nèi)核代碼需要消耗CPU資源,和可能需要IO操作來(lái)將數(shù)據(jù)字典信息插入row cache中。

游標(biāo)是使用共享池中的數(shù)據(jù)來(lái)創(chuàng)建的,如果數(shù)據(jù)當(dāng)前不在共享池中,Oracle將創(chuàng)建它自己的SQL語(yǔ)句來(lái)從數(shù)據(jù)字典表中檢索數(shù)據(jù)。Oracle動(dòng)態(tài)創(chuàng)建的SQL會(huì)命名為遞歸SQL并運(yùn)行它。為了創(chuàng)建一個(gè)游標(biāo)Oracle需要的數(shù)據(jù)是優(yōu)化器統(tǒng)計(jì)信息,會(huì)話信息,安全信息,對(duì)象信息與對(duì)象關(guān)聯(lián)信息。

游標(biāo)是由稱為堆的共享池內(nèi)存塊創(chuàng)建的。傳統(tǒng)上,不同的SQL語(yǔ)句需要不同大小的內(nèi)存塊。常見(jiàn)的SQL語(yǔ)句通常請(qǐng)求4KB大小的內(nèi)存塊。與free exten管理一樣,請(qǐng)求不一致大小的內(nèi)存塊會(huì)導(dǎo)致分配,性能與效率問(wèn)題。從Oracle 10gr2開(kāi)始,Oracle將所有的內(nèi)存塊定義為4KB。當(dāng)合適的內(nèi)存塊不能快速地找到時(shí),Oracle最終可能會(huì)放棄并posts一個(gè)4031錯(cuò)誤“out of shared poll memory”并停止SQL語(yǔ)句的處理。

Cursor Searching Introduction
與buffer cache中的每個(gè)buffer一樣,每個(gè)父游標(biāo)與子游標(biāo)必須被定位并且搜索必須要快速。這將請(qǐng)求內(nèi)存,一個(gè)搜索結(jié)構(gòu),序列化,內(nèi)核代碼與大量CPU資源。

因?yàn)橛螛?biāo)與程序結(jié)構(gòu)存放在library cache中,有一個(gè)結(jié)構(gòu)來(lái)定位對(duì)象。Oracle選擇使用哈希算法與相關(guān)哈希類似結(jié)構(gòu)。解析操作的一部分是判斷一個(gè)游標(biāo)當(dāng)前是否存放在library cache中了。如果確實(shí)在library cache中找到了這個(gè)游標(biāo),進(jìn)行了一些解析操作,因此它確實(shí)是一個(gè)軟解析。然而如果在library cache中沒(méi)有找到這個(gè)游標(biāo),整個(gè)游標(biāo)需要被創(chuàng)建,因此它就是硬解析。游標(biāo)創(chuàng)建與硬解析是相當(dāng)昂貴的操作。

Cursor Pinning and Locking
固定游標(biāo)類似于固定buffer。它被用來(lái)確保當(dāng)游標(biāo)被引用時(shí)不會(huì)被回收(有時(shí)也叫破壞)。游標(biāo)顯然不是關(guān)系結(jié)構(gòu),但是SQL與關(guān)系結(jié)構(gòu)(例如employee表)相關(guān),關(guān)系結(jié)構(gòu)用于構(gòu)建游標(biāo)(例如sys.col$),因此使用了鎖——也就是說(shuō),使用了隊(duì)列。游標(biāo)隊(duì)列也叫作CU隊(duì)列并且就像其它隊(duì)列一樣通過(guò)Oracle的等待接口可以檢測(cè)。

當(dāng)創(chuàng)建與執(zhí)行游標(biāo)時(shí)就要固定游標(biāo)。這是很容易理解的,當(dāng)你創(chuàng)建一個(gè)游標(biāo)時(shí),它是一種內(nèi)存結(jié)構(gòu),你不想其它的進(jìn)程回收相關(guān)的內(nèi)存。正常情況下,游標(biāo)在創(chuàng)建與執(zhí)行完成后不會(huì)出現(xiàn)固定的情況。這意味著在你執(zhí)行一個(gè)游標(biāo)后且等待2分鐘后你想再次執(zhí)行相同的游標(biāo),這時(shí)游標(biāo)可能已經(jīng)被回收了。如果出現(xiàn)這種情況,在library cache中找不到需要的游標(biāo),將會(huì)執(zhí)行硬解析,它將完全重新創(chuàng)建游標(biāo)。

在創(chuàng)建與執(zhí)行游標(biāo)時(shí)也可能會(huì)出現(xiàn)鎖定的情況。但它不同于固定游禁。固定的關(guān)注點(diǎn)在于內(nèi)存回收。而鎖是確保與游標(biāo)相關(guān)的表在創(chuàng)建與執(zhí)行游標(biāo)時(shí)不被修改。顯然,這可能會(huì)造成一些相當(dāng)奇怪的情況,而Oracle不會(huì)允許這種情況發(fā)生。

“Oracle Cursor的相關(guān)知識(shí)點(diǎn)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI