程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> 全面講解Oracle鎖存器

全面講解Oracle鎖存器

編輯:Oracle數據庫基礎

Oracle有很多值得學習的地方,這裡我們主要介紹Oracle鎖存器,包括介紹Oracle的讀一致性機制等方面。Oracle鎖的機制,分Oracle鎖存器和鎖兩種。鎖存器是用來保護對內存結構的訪問,比如對DB BUFFER中塊的鎖存器申請,只有在DBWN完成後,這些DB BUFFER塊被解鎖。然後用於其它的申請。

Oracle鎖存器不可以在進程間共享,鎖存器的申請要麼成功要麼失敗,沒有鎖存器申請隊列。主要的Oracle鎖存器有SHARED POOL鎖存器,LIBRARY CACHE鎖存器,CACHE BUFFERS LRU CHAIN鎖存器,CACHE BUFFERS CHAINS鎖存器,REDO ALLOCATION鎖存器,REDO COPY鎖存器。

Oracle的鎖是用來保護數據訪問的,鎖的限制比鎖存器要更寬松,比如,多個用戶在修改同一表的不同行時,可以共享一個表上的一個鎖,鎖的申請可以按照被申請的順序來排隊等候,然後依次應用,這種排隊機制叫做隊列(ENPUEUE),如果兩個服務器進程試圖對同一表的同一行進行加鎖,則都進入鎖的申請隊列,先進的加鎖成功,後面的進程要等待,直到前一個進程解鎖才可以加鎖,這叫做鎖的爭用,而且一旦加鎖成功,這個鎖將一直保持到用戶發出COMMIT或ROOLBACK命令為止。

如果兩個用戶鎖定各自的一行並請求對方鎖定的行的時候將發生無限期等待即死鎖,死鎖的發生都是由於鎖的爭用而不是鎖存器的爭用引起的,Oracle在遇到死鎖時,自動釋放其中一個用戶的鎖並回滾此用戶的改變。正常情況下發生鎖的爭用時,數據的最終保存結果由SCN來決定哪個進程的更改被最終保存。兩個用戶的服務器進程在申請同一表的多個行的鎖的時候是可以交錯進入鎖的申請隊列的。只有其中發生爭用才會進行等待。創建表時指定的MAXTRANS參數決定了表中的一個數據塊同時最多可以被幾個事務鎖定。

下面來講一下Oracle的讀一致性機制,Oracle的讀一致性保證了事務之間的高度隔離性。下面是幾個關於回滾段讀一致性和死鎖的事例:

一、大SELECT,小UPDATE
A會話----Select * from test;----設scn=101----執行時間09:10:11
B會話-----Update test set id=9999999 where id=1000000----設scn=102-----執行時間09:10:12

我們會發現B會話會在A會話前完成,A會話中顯示的ID=100000是從回滾段中讀取的,因為A會話在讀到ID=1000000所在的BLOCK時發現BLOCK上有事務信息,因此要從回滾段中讀,如果UPDATE在SELECT讀到此BLOCK之前已經COMMIT,則SELECT讀到此BLOCK時發現其BLOCK上沒有事務信息,但是會發現其BLICK的SCN比SELECT自己的SCN大,因此也會利用回滾段進行重構。根據當前塊上所有的itl找到相應的undo地址,重構出之前的block image,之前的那個block又含有自己的itl信息.如果這個before image中對應的scn不滿足查詢,又會根據undo生成beforebeforeimage,這樣不斷往復,直到構造出符合查詢的scn的block返回結果,或者系統實在無法根據undo構造出符合查詢的block,,報ora-01555的錯誤為止....。需要強調的是讀一致性是通過對當前整個塊利用回滾段(當前塊上的所有ITL記錄的所有回滾段地址)進行遞歸重構到過去某一時間點或某一SCN的塊的一致性快照。而不是只針對塊中一部分ITL記錄在回滾段中遞歸查找來完成的,一定要理解遞歸重構與遞歸查找是完全不同的兩個概念。Oracle回滾段確保了事務的高度的隔離性。即只要回滾段足夠大,那麼一個SELECT不管執行多長,它讀取的所有數據都將是在這條SELECT語句開始執行瞬間這個時間點的值,而不會被其它用戶在SELECT讀取期間對數據是否做過修改而影響。

二、大UPDATE,小SELECT
A會話----Update test set id=1;----設scn=101----執行時間09:10:11
B會話-----select * from test where id=1000000----設scn=102-----執行時間09:10:12

我們會發現B會話會在A會話前完成,B會話中顯示的ID=1000000是從BLOCK中直接讀取的,因為B會話在讀到ID=1000000所在的BLOCK時,A會話還沒有來得及對其鎖定,因此B會話既不會發現BLOCK上有事務信息,也不會發現BLOCK上的SCN比SELECT的大,因此會從BLOCK中直接讀取,如果SELECT在UPDATE鎖定此BLOCK後才發出,B會話讀到此BLOCK時發現其BLOCK上有事務信息,因此會從回滾段中讀取。

三、大UPDATE,小UPDATE
A會話----Update test set id=1;----設scn=101----執行時間09:10:11
B會話1-----Update test set id=999999 where id=1000000----設scn=102-----執行時間09:10:12
B會話2----- select * from test where id=2----設scn=103-----執行時間09:10:14
B會話3----- update test set id=3 where id=2----設scn=104-----執行時間09:10:15

我們會發現B會話1會完成,A會話將一直等待,因為B會話1會先於A會話鎖定ID=1000000所在的BLOCK,並改寫頭部的事務信息,A會話在試圖鎖定此BLOCK時,發現其上有事務信息,將會一直等待B會話1事務結束後再行鎖定,B會話2查詢到的ID=2是從回滾段中讀取的而不是從BLOCK中直接讀出來的。因為A會話已將ID=2的BLOCK鎖定,並寫入了回滾段,從B會話3可以證明這一點,B會話3發出後,B會話3會收到死鎖的信息,死鎖的原因是A會話在等待B會話對ID=1000000所在的BLOCK解鎖,現在B會話又在等待A會話對ID=2所在的BLOCK解鎖,因此形成死鎖,因此證明ID=2所在的BLOCK已被A會話鎖定,然後A會話也會收到死鎖的信息。以上介紹Oracle鎖存器。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved