Oracle鎖基礎知識

路途中的人2012發表於2016-05-21
001 引言
    在任何多使用者資料庫應用程式中,最終免不了會出現兩個使用者希望同時使用同一行的情況。資料庫必須確保這在物理上不可能實現。事務的隔離性原則要求資料庫確保:在一個會話的事務完成之前,另一個會話的事務不能影響此會話。為此,資料庫必須對資料的併發訪問進行序列化,必須確保即使多個會話請求同一行,它們實際上要按順序排隊。
    藉助於記錄和表鎖定機制,我們可以實現併發訪問的序列化。Oracle資料庫中的鎖定是完全自動的。一般而言,只有在軟體用質量較差的程式碼干擾自動鎖定機制時,或業務分析出錯導致會使會話發生衝突的業務模型時,才會引發某些問題。

002 共享鎖與排它鎖
    Oracle資料庫中鎖定的標準級別保證了最大可能的併發級別。也就是說,如果某個會話正在更新一行,那麼只有這行會被鎖定。此外鎖定這一行只是為了防止其它會話對其進行更新,其它會話可以隨時執行讀取操作。只有在使用commit或rollback命令結束事務之後,鎖定才會被解除。這種鎖定是一個“排它(exclusive)”鎖:在指定記錄上請求排它鎖的第一個會話會得到這個鎖定,其它請求對該記錄進行寫訪問的會話則必須等待。雖然這一行已透過鎖定會話進行了更新,但是對其進行讀訪問是被允許的(而且經常會出現這種情況),並且這些讀操作會涉及撤銷資料的使用,從而確保讀會話並不會看到任何未被提交的變更。
    對於一行或一個完整表上的排它鎖來說,每次只能有一個會話可以獲得這個排它鎖,不過許多會話可以同時獲得同一物件上的“共享(shared)”鎖。在一行上設定共享鎖毫無意義,其原因在於鎖定一行的唯一目的就是不允許其它會話更改它。共享鎖被置於整個表上,同時許多會話可以獲得同一個表上的共享鎖。在一個表上放置共享鎖的目的是為了防止另一個會話獲得這個表上的排它鎖(在已存在共享鎖的情況下無法再獲得排它鎖)。在表上放置排它鎖時需要執行DDL語句。如果其它會話已經在一個表上放置共享鎖,那麼我們就無法執行修改某個物件的語句(例如刪除這個表的一列)。
    為了在行上執行DML語句,當前會話必須獲得待更改行上的排它鎖以及包含這些行的表上的共享鎖。如果另一個會話已經獲取了待更改行上的排它鎖,那麼當前會話將被掛起,直至使用commit或rollback命令解除這些鎖定。如果另一個會話已經獲取了表上的共享鎖以及其它行上的排它鎖,那麼就不存在任何問題。一個表上的排它鎖也是允許的,但是,除非DDL語句要求這麼做,預設鎖定機制是不鎖定整個表。
    所有DML語句至少都需要兩種鎖:受影響記錄上的排它鎖,以及包含受影響記錄的表上的共享鎖。排它鎖能夠防止其它會話干預指定的行,而共享鎖則能夠組織其它會話使用DDL語句修改表的定義。這兩種鎖定會被自動請求。如果某條DML語句在指定記錄上無法獲取所需的排它鎖,那麼會掛起這條語句直至獲得所需的排它鎖。
    執行DDL命令需要使用所涉及物件上的排它鎖。只有在針對指定表的所有DML事務結束,且行上的排它鎖以及表上的共享鎖都被解除之後,我們才可以獲得執行DDL命令所需的排它鎖。任何DDL語句所需的排它鎖都是被自動請求的。但是,如果無法獲取所需的排它鎖(通常是因為其它會話已經獲得用於 DML語句的共享鎖),那麼DDL語句會由於錯誤立即終止。

003 排隊機制
    請求鎖定需要排隊。如果某個會話請求一個鎖定,但由於其它會話已經鎖定了指定行或物件而無法獲得所需的鎖定,那麼這個會話將會等待。此時,可能有多個會話都在等待訪問相同的記錄或物件,在這種情況下,Oracle會跟蹤這些會話請求鎖定的順序。當使用鎖定的會話解除鎖定時,下一個會話將獲得授權,以此類推。這種機制被稱為“排隊(enqueue)”機制。
    如果不希望某個會話在無法獲取鎖定時進行排隊,那麼避免排隊的唯一方式是使用select...for update命令的wait或nowait子句。因為select語句並不需要任何鎖定,所以普通的select語句能夠成功地執行,但是,DML語句則會被掛起。


未完待續




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