PostgreSQL學習手冊(七) 事物隔離

來源:互聯網
上載者:User

    在SQL的標準中事物隔離等級分為以下四種:
    1. 讀未提交(Read uncommitted)
    2. 讀已提交(Read committed)
    3. 可重複讀(Repeatable read)
    4. 可序列化(Serializable)
    然而PostgreSQL在9.1之前的版本中只是實現了其中兩種,即讀已提交和可序列化,如果在實際應用中選擇了另外兩種,那麼PostgreSQL 將會自動向更嚴格的隔離等級調整。在PostgreSQL v9.1的版本中提供了三種實現方式,即在原有的基礎上增加了可重複讀。在這篇部落格中我們將只是針對2)和4)進行說明和比較,因為在9.1中,3)和 4)的差別也是非常小的。

  讀已提交 可序列化
PostgreSQL預設隔離等級
其它事物未提交資料是否可見 不可見 不可見
執行效率
適用情境 簡單SQL邏輯,如果SQL語句中含有巢狀查詢,那麼在多次SQL查詢中將極有可能獲得不同版本的資料。 複雜SQL邏輯,特別是帶有嵌套的查詢比較適用。
SELECT查詢一致性時間點 從該SELECT查詢開始執行時,在此查詢執行期間,任何其它並發事物針對該查詢結果集的資料操作都將不會被本次查詢讀到,即本次查詢擷取的資料版本是與查詢開始執行時的資料版本相一致。 從該SELECT查詢所在事物開始時,在此查詢執行期間,任何其它並發事物針對該查詢結果集的資料操作都將不會被本次查詢讀到,即本次查詢擷取的資料版本是與查詢所在事物開始時的資料版本相一致。
同事物內的資料操作是否可見 比如在同一個事物記憶體在update和select操作,即使當前事物尚未提交,update所作的修改,在當前事物後面的select中依然可見。 和讀已提交相同。
同事物內多次相同的select所見的資料是否相同 不同,由於該層級select的一致性時間點是該查詢開始執行時,而多次查詢的時間點將肯定不相同,如果在第一次查詢開始到第二次查詢開始之間,其它的並發事物修改並提交或當前事物僅修改了查詢將要擷取的資料,那麼這些資料操作的結果將會在第二個查詢中有所體現。 需要分兩步來說,對於同一事物內的修改如果發 生在兩次查詢語句之間,那麼第二個查詢將會看到這些修改的結果。然而對於其它並發事物的修改,將不會造成任何影響,即兩次select的結果是相同的。原 因顯而易見,該隔離等級的select一致性時間點是與事物開始時相一致的。
相同行資料的修改 如果此時兩個並發事物在修改同一行資料,先修 改的事物將會給該行加行級鎖,另外一個事物將進入等待狀態,直到第一個事物操作該行結束。那麼倘若第一個針對該行的修改操作最終被其事物復原,第二個修改 操作在結束等待後,將直接修改該資料。然而如果第一個操作是被正常提交的話,那麼就需要進一步判斷該操作的類型,如果是刪除(delete)該行,第二個 修改操作將直接被忽略。如果是update該行的記錄,第二個修改操作則需要重新評估該行是否依然符合之前定義的修改條件。 和讀已提交隔離等級的機制基本相同,只是在第 一個修改操作提交後,第二個操作將不再區分之前的修改是delete還是update,而是直接並返回下面資訊:Error: Can't serialize access due to concurrent update. 這是因為一個可序列化的事務在可序列化事務開始之後不能更改或者鎖住被其他事務更改過的行。因此,當應用收到這樣的錯誤資訊時,它應該退出當前的事務然後 從頭開始重新進行整個事務。在應用程式中,也應該有必要的代碼來專門處理該類錯誤。

    最後需要說明的是,在絕大多數的情況下,讀已提交層級均可適用,而且該層級的並發效率更高。只有在比較特殊的情況下,才手工將當前的事物隔離等級調整為可序列化或可重複讀。

    在SQL的標準中事物隔離等級分為以下四種:
    1. 讀未提交(Read uncommitted)
    2. 讀已提交(Read committed)
    3. 可重複讀(Repeatable read)
    4. 可序列化(Serializable)
    然而PostgreSQL在9.1之前的版本中只是實現了其中兩種,即讀已提交和可序列化,如果在實際應用中選擇了另外兩種,那麼PostgreSQL 將會自動向更嚴格的隔離等級調整。在PostgreSQL v9.1的版本中提供了三種實現方式,即在原有的基礎上增加了可重複讀。在這篇部落格中我們將只是針對2)和4)進行說明和比較,因為在9.1中,3)和 4)的差別也是非常小的。

  讀已提交 可序列化
PostgreSQL預設隔離等級
其它事物未提交資料是否可見 不可見 不可見
執行效率
適用情境 簡單SQL邏輯,如果SQL語句中含有巢狀查詢,那麼在多次SQL查詢中將極有可能獲得不同版本的資料。 複雜SQL邏輯,特別是帶有嵌套的查詢比較適用。
SELECT查詢一致性時間點 從該SELECT查詢開始執行時,在此查詢執行期間,任何其它並發事物針對該查詢結果集的資料操作都將不會被本次查詢讀到,即本次查詢擷取的資料版本是與查詢開始執行時的資料版本相一致。 從該SELECT查詢所在事物開始時,在此查詢執行期間,任何其它並發事物針對該查詢結果集的資料操作都將不會被本次查詢讀到,即本次查詢擷取的資料版本是與查詢所在事物開始時的資料版本相一致。
同事物內的資料操作是否可見 比如在同一個事物記憶體在update和select操作,即使當前事物尚未提交,update所作的修改,在當前事物後面的select中依然可見。 和讀已提交相同。
同事物內多次相同的select所見的資料是否相同 不同,由於該層級select的一致性時間點是該查詢開始執行時,而多次查詢的時間點將肯定不相同,如果在第一次查詢開始到第二次查詢開始之間,其它的並發事物修改並提交或當前事物僅修改了查詢將要擷取的資料,那麼這些資料操作的結果將會在第二個查詢中有所體現。 需要分兩步來說,對於同一事物內的修改如果發 生在兩次查詢語句之間,那麼第二個查詢將會看到這些修改的結果。然而對於其它並發事物的修改,將不會造成任何影響,即兩次select的結果是相同的。原 因顯而易見,該隔離等級的select一致性時間點是與事物開始時相一致的。
相同行資料的修改 如果此時兩個並發事物在修改同一行資料,先修 改的事物將會給該行加行級鎖,另外一個事物將進入等待狀態,直到第一個事物操作該行結束。那麼倘若第一個針對該行的修改操作最終被其事物復原,第二個修改 操作在結束等待後,將直接修改該資料。然而如果第一個操作是被正常提交的話,那麼就需要進一步判斷該操作的類型,如果是刪除(delete)該行,第二個 修改操作將直接被忽略。如果是update該行的記錄,第二個修改操作則需要重新評估該行是否依然符合之前定義的修改條件。 和讀已提交隔離等級的機制基本相同,只是在第 一個修改操作提交後,第二個操作將不再區分之前的修改是delete還是update,而是直接並返回下面資訊:Error: Can't serialize access due to concurrent update. 這是因為一個可序列化的事務在可序列化事務開始之後不能更改或者鎖住被其他事務更改過的行。因此,當應用收到這樣的錯誤資訊時,它應該退出當前的事務然後 從頭開始重新進行整個事務。在應用程式中,也應該有必要的代碼來專門處理該類錯誤。

    最後需要說明的是,在絕大多數的情況下,讀已提交層級均可適用,而且該層級的並發效率更高。只有在比較特殊的情況下,才手工將當前的事物隔離等級調整為可序列化或可重複讀。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.