您好,登錄后才能下訂單哦!
本篇內容介紹了“Oracle Cursor的相關知識點有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
游標是一個基本對象,它是SQL語句或PL/SQL編程式構造的一種完整可執行表示,可以被任何授權會話使用和重用。游標必須被創建,定位(通過搜索來查找),消毀(回收),失效與重載。如果游標的任何部分不在共享池中,并且出于任何原因需要,則必須重新加載該游標,這會降低性能。
開發人員通常對游標有很好的理解因為他們需要專門創建,打開,執行,獲取與關閉游標。DBA通常將游標作為與SQL相關的簡單內存塊來看待。然而,這種過于簡單的關點限制了我們為與游標相關的性能問題創建解決方案的能力。因此,如果花時間更好地理解游標,將會注意到性能解決方案選項將顯著增加。
父游標與子游標
游標這個術語本身是一個抽象概念,用來引用共享的信息(位于共享SQL區),私有信息(位于會話的PGA)與用來定位各種游標組件的library cache chain節點(當引用library cache時就叫作handle)。不幸地是這種多用途的定義也增加了混淆。當一個游標被關閉時,Oracle不會簡單的回收這三個游標組件。而是Oracle可能會按需來回收游標組件。
一個游標第一次執行時,會存在一個父游標與子游標。后續的會話,即使相同的會話執行相同的SQL語句(哈希值相同),可能會使用不同的子游標。雖然SQL語句在文本上完全相同,但是創建子游標是為了捕獲特定的特征,比如優化模式的差異(例如first_rows),這會導致不同的執行計劃或不同的會話級參數(cursor_sharing=similar)。下面的例子簡單的顯示了相同會話執行相同SQL語句兩次,只是在兩次執行之間執行了alter session命令,這足以強制創建一個額外的子游標。trace命令用來證明創建了兩個子游標。
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
下面的內容是上面的trace命令所創建的跟蹤文件中的一部分內容。我們通過搜索select * from dual來定位我們關心的內容并檢查SQL語句。此時,我們感興趣的是,這條SQL語句僅由一個會話執行,但它創建了兩個子游標。
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
庫緩存對象之間的關系不僅為執行目的而必須維護,而且當其中一個組件發生更改時也必須維護。假設一個表被2000個SQL語句,100個函數與20個包所引用。現在假設表的一列被重命名。Oracle將會使所有相關的SQL語句與程序結構失效。這可能導致在請求latching與locking時出現級聯效應。多個相關會話、失效、重新編譯和計時的組合導致整個Oracle實例被鎖定。很明顯Oracle已經知道了這種問題的嚴重性并且積極的減小出現這種情況的可能性。但每個DBA要了解library cache之間的關系是非常復雜的并且有時可能導致出現問題。
Cursor Building
當在library cache中搜索并沒有找到游標時就會創建游標。這就是硬解析。很明顯這是一個相對昂貴的操作它需要請求內存管理(分配與可能回收),使用latching來確保序列化,使用locking來阻止不合適的更改,執行內核代碼需要消耗CPU資源,和可能需要IO操作來將數據字典信息插入row cache中。
游標是使用共享池中的數據來創建的,如果數據當前不在共享池中,Oracle將創建它自己的SQL語句來從數據字典表中檢索數據。Oracle動態創建的SQL會命名為遞歸SQL并運行它。為了創建一個游標Oracle需要的數據是優化器統計信息,會話信息,安全信息,對象信息與對象關聯信息。
游標是由稱為堆的共享池內存塊創建的。傳統上,不同的SQL語句需要不同大小的內存塊。常見的SQL語句通常請求4KB大小的內存塊。與free exten管理一樣,請求不一致大小的內存塊會導致分配,性能與效率問題。從Oracle 10gr2開始,Oracle將所有的內存塊定義為4KB。當合適的內存塊不能快速地找到時,Oracle最終可能會放棄并posts一個4031錯誤“out of shared poll memory”并停止SQL語句的處理。
Cursor Searching Introduction
與buffer cache中的每個buffer一樣,每個父游標與子游標必須被定位并且搜索必須要快速。這將請求內存,一個搜索結構,序列化,內核代碼與大量CPU資源。
因為游標與程序結構存放在library cache中,有一個結構來定位對象。Oracle選擇使用哈希算法與相關哈希類似結構。解析操作的一部分是判斷一個游標當前是否存放在library cache中了。如果確實在library cache中找到了這個游標,進行了一些解析操作,因此它確實是一個軟解析。然而如果在library cache中沒有找到這個游標,整個游標需要被創建,因此它就是硬解析。游標創建與硬解析是相當昂貴的操作。
Cursor Pinning and Locking
固定游標類似于固定buffer。它被用來確保當游標被引用時不會被回收(有時也叫破壞)。游標顯然不是關系結構,但是SQL與關系結構(例如employee表)相關,關系結構用于構建游標(例如sys.col$),因此使用了鎖——也就是說,使用了隊列。游標隊列也叫作CU隊列并且就像其它隊列一樣通過Oracle的等待接口可以檢測。
當創建與執行游標時就要固定游標。這是很容易理解的,當你創建一個游標時,它是一種內存結構,你不想其它的進程回收相關的內存。正常情況下,游標在創建與執行完成后不會出現固定的情況。這意味著在你執行一個游標后且等待2分鐘后你想再次執行相同的游標,這時游標可能已經被回收了。如果出現這種情況,在library cache中找不到需要的游標,將會執行硬解析,它將完全重新創建游標。
在創建與執行游標時也可能會出現鎖定的情況。但它不同于固定游禁。固定的關注點在于內存回收。而鎖是確保與游標相關的表在創建與執行游標時不被修改。顯然,這可能會造成一些相當奇怪的情況,而Oracle不會允許這種情況發生。
“Oracle Cursor的相關知識點有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。