笑看風云

          一切從頭開始
          posts - 28, comments - 1, trackbacks - 0, articles - 2

          postgres隔離級別

          Posted on 2008-12-11 11:48 笑看風云 閱讀(447) 評論(0)  編輯  收藏 所屬分類: 數據庫
          多版本并行控制(Multi-Version Concurrency Control (MVCC))是用于提高數據庫在一個多用戶環境下性能的高級技術。Vadim Mikheev 為 Postgres 提供了MVCC的實現。

          介紹

          與其他使用鎖來進行并行控制的數據庫系統不同,Postgres 利用多版本模型來維護數據的一致性。這就意味著當檢索數據庫時,每個事務都看到一個數據的一段時間前的快照(一個 數據庫版本),而不管正在處理的數據當前的狀態。這樣,如果對每個數據庫會話進行 事務隔離,就可以避免一個事務看到因為其它并行的事務更新同一行數據而導致的不連貫的數據。 
          多版本和鎖定模型的主要區別是在 MVCC 里,對檢索(讀)數據的鎖要求與寫數據的鎖要求不沖突,所以讀不會阻塞寫,而寫也從不阻塞


          ▲事務隔離

          ANSI
          /ISOSQL 用三個必須在并行的事務之間避免的現象定義了四個級別的事務隔離。這些不希望發生的現象是: 
          讀污染(dirty reads) 
          一個事務讀取了被另一個未提交的并行的事務寫的數據。 
          不可重復的讀(non
          -repeatable reads) 
          一個事務重新讀取前面讀取過的數據,發現該數據已經被另一個已提交的事務修改過。 
          錯誤讀取(phantom read) 
          一個事務重新執行一個查詢,返回一套符合查詢條件的行,發現這些行中插入了被其他已提交的事務提交的行。 
          這四種隔離級別和對應的特性在下面描述。 
          表 
          13-1. Postgres 隔離級別 



          ▲讀已提交隔離級別

          讀已提交(Read Committed)是Postgres 里的缺省隔離級別。當一個事務運行在這個隔離級別時,一個查詢只能看到查詢開始之前的數據而永遠無法看到臟數據或者是在查詢執行時其他并行的事務提交做的改變。 
          如果一個正在執行一個 UPDATE 語句(或者 DELETE 或者 SELECT FOR UPDATE)的查詢返回的行正在被另一個并行的未提交的事務更新,那么第二個試圖更新此行的事務將等待另一個事務的提交或者回卷。如果發生了回卷,等待中的事務可以繼續修改此行。如果發生了提交(并且此行仍然存在;也就是說,沒有被另一個事務刪除),這個查詢將對該行再執行一便以檢查新行版本是否滿足查詢搜索條件。如果新行版本滿足查詢搜索條件,那么該行將被更新(或刪除或被標記為更新)。 

          注意 SELECT 或 INSERT 語句執行的結果(在一個查詢里)將不會被并行事務影響。

          可串行化隔離級別
          可串行化(Serializable)提供最高級別的事務隔離。當一個事務處于可串行化級別,一個查詢只能看到在事務開始之前提交的數據而永遠看不到臟數據或事務執行中其他并行事務提交的修改。所以,這個級別模擬串行事務執行,就好象事務將被一個接著一個那樣串行的,而不是并行的執行。 
          如果一個正在執行一個 UPDATE 語句(或者 DELETE 或者 SELECT FOR UPDATE)的查詢返回的行正在被另一個并行的未提交的事務更新,那么第二個試圖更新此行的事務將等待另一個事務的提交或者回卷。如果發生了回卷,等待中的事務可以繼續修改此行。如果發生一個并行的事務的提交,一個可串行化的事務將回卷,并返回下面信息。 

          ERROR: Can´t serialize access due to concurrent update

          因為一個可串行化的事務在可串行化事務開始之后不能更改被其他事務更改過的行。 
          注意: SELECT 或 INSERT 語句執行的結果(在一個查詢里)將不會被并行事務影響。


          ▲鎖和表

          Postgres 提供多種鎖模式來控制對表中數據的并行訪問。有些鎖模式是在語句執行之前由Postgres 自動施加的,而其他的提供用來由應用使用的。一個事務里要求的所有鎖模式(除了 AccessShareLock)都是在整個事務期間保有的。 
          除了鎖以外,短期的共享
          /排他銷也在共享的緩沖池中用于控制對表頁面的讀/寫訪問。銷在一條記錄抓取或者更新后馬上被釋放。 


          表級鎖

          AccessShareLock 
          一個內部鎖模式,進行查詢時自動施加在被查詢的表上。語句執行完成后,Postgres 釋放這些鎖。 

          只與 AccessExclusiveLock 沖突。 

          RowShareLock 
          被 SELECT FOR UPDATE 和用于 IN ROW SHARE MODE 的 LOCK TABLE 語句要求。 

          與 ExclusiveLock 和 AccessExclusiveLock 模式沖突。 

          RowExclusiveLock 
          被 UPDATE, DELETE, INSERT 和用于IN ROW EXCLUSIVE MODE 的 LOCK TABLE 語句要求。 

          與 ShareLock,ShareRowExclusiveLock,ExclusiveLock 和 AccessExclusiveLock 模式沖突。 


          ShareLock 
          被 CREATE INDEX 和用于IN SHARE MODE 的 LOCK TABLE 語句所要求。 

          與 RowExclusiveLock,ShareRowExclusiveLock,ExclusiveLock 和 AccessExclusiveLock 模式沖突。 

          ShareRowExclusiveLock 
          被用于 IN SHARE ROW EXCLUSIVE MODE 的 LOCK TABLE 語句要求。 

          與 RowExclusiveLock,ShareLock,ShareRowExclusiveLock,ExclusiveLock 和 AccessExclusiveLock 模式沖突。 

          ExclusiveLock 
          被用于 IN EXCLUSIVE MODE 的 LOCK TABLE 語句要求。 

          與 RowShareLock,RowExclusiveLock,ShareLock,ShareRowExclusiveLock,ExclusiveLock 和 AccessExclusiveLock 模式沖突。 

          AccessExclusiveLock 
          被 ALTER TABLE,DROP TABLE,VACUUM 和 LOCK TABLE 語句要求。 

          與 RowShareLock,RowExclusiveLock,ShareLock,ShareRowExclusiveLock,ExclusiveLock 和 AccessExclusiveLock 模式沖突。 



          注意:
          只有 AccessExclusiveLock 阻塞 SELECT (沒有 FOR UPDATE)語句。
          行級鎖
          當某行的一個內部字段被更新(或刪除或標記為更新)時要求使用這些鎖。Postgres 在內存里不做關于已更新的行的任何記憶,因而對鎖定的行數沒有任何限制,也沒有鎖定遞增。 
          但是,要注意 SELECT FOR UPDATE 會更改所選定的行以標記它們,因而會導致磁盤寫動作。 

          行級別的鎖不影響數據查詢。它們只是用于阻塞對同一行的寫。


          鎖和索引

          盡管 Postgres 提供對表數據訪問的非阻塞的讀
          /寫,但并非所有Postgres 里實現的索引訪問模式都能夠進行非阻塞讀/寫。 
          各種各樣的索引類型按照下面方法操作: 

          GiST 和 R
          -Tree 索引 
          共享
          /排他的索引級鎖用于讀/寫訪問。鎖在語句完成后釋放。 
          Hash (散列)索引 
          共享
          /排他的頁面級鎖用于讀/寫訪問。鎖在頁面處理完成后釋放。 

          頁面級鎖比索引級的鎖提供了更好的并行性但是容易產生死鎖。 

          Btree 
          短期的共享
          /排他的頁面級的銷用于讀/寫訪問。銷在索引記錄被插入/抓取后立即釋放。 
          Btree 索引提供了無死鎖條件的最高級的并行性。 


          應用層的數據完整性檢查

          因為對 Postgres 的讀動作不會鎖定數據,不管事務是何隔離級別,一個事務讀取的數據可能被另一個事務覆蓋。換句話說,如果一條 SELECT 返回了一行,這并不意味著在返回該行時該行還存在(比如說在語句完成或事務開始后的某時)也不意味著在當前事務做提交或者回卷前該行被保護不被并行的事務刪除或更新。 
          要保證一行的實際存在和避免其被并行更新,我們必須使用 SELECT FOR UPDATE 或者合適的 LOCK TABLE 語句。當從其他環境向 Postgres 里用可串行化模式移植應用時一定要把這些問題考慮進去。 

          注意: 在版本 
          6.5 前,Postgres 使用讀動作鎖,因而當從以前的 Postgres 版本向6.5(或更高版本)升級時也要考慮這些問題。
          Postgres 隔離級別


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 唐海县| 陕西省| 五华县| 治县。| 高要市| 沁源县| 明星| 辽阳市| 嘉鱼县| 阿拉善右旗| 庆阳市| 子洲县| 玛多县| 五大连池市| 汤阴县| 柳江县| 南乐县| 镇平县| 万年县| 闽清县| 太仆寺旗| 融水| 鹤庆县| 利辛县| 东乌| 大理市| 惠安县| 昭苏县| 南昌市| 嘉黎县| 金山区| 喜德县| 内丘县| 东莞市| 神池县| 丰城市| 普安县| 拉孜县| 环江| 印江| 苗栗县|