2PL(兩階段鎖定)算法如何工作
2PL(兩階段鎖定)算法是關係數據庫系統用來保證數據完整性的最古老的併發控制機制之一。
在本文中,我將解釋 2PL 算法如何工作以及如何以任何編程語言實現它。
鎖類型
在我們開始討論 2PL 算法實現之前,解釋讀和寫鎖的工作方式非常重要。
1.讀鎖:讀取或共享鎖定可防止在併發讀取的同時寫入。
2.寫鎖:寫鎖或排他鎖不允許對給定資源進行讀和寫操作。
某些數據庫系統(例如 PostgreSQL,MySQL 或 SQL Server)提供了獲取指定元組或元組範圍上的讀取和寫入鎖的可能性。其他數據庫系統(例如 Oracle)僅允許通過 FOR UPDATE 子句獲取寫 / 獨佔鎖。
但是,讀和寫鎖不僅限於數據庫系統。傳統上,進入 Java synchronized 塊允許獲取排他鎖,從 1.5 版開始,Java 允許通過 ReentrantReadWriteLock 對象進行讀寫鎖。
兩相鎖定 / 兩段鎖
僅鎖是不足以防止衝突。併發控制策略必須定義如何獲取和釋放鎖,因爲這也會影響事務交織。
爲此,2PL 協議定義了一種鎖定管理策略,以確保嚴格的可序列化性。
2PL 協議將事務分爲兩部分:
-
擴展階段(獲取鎖,並且不允許釋放鎖)
-
收縮階段(釋放所有鎖,並且無法進一步獲取其他鎖)。
對於數據庫事務,擴展階段意味着允許從事務開始到結束爲止獲取鎖,而收縮階段由提交或回滾階段表示,就像在事務結束時一樣,所有已獲取的鎖鎖被釋放。
下圖顯示了 2PL 如何協調事務交織:
-
愛麗絲(Alice)和鮑勃(Bob)都 post 通過 SELECT FOR SHARE 的 PostgreSQL 語句獲得了對指定記錄的讀取鎖定。
-
當 Bob 嘗試對 post 條目執行 UPDATE 語句時,其語句被鎖管理器阻止,因爲 UPDATE 語句需要在該 post 行上獲取寫鎖,而 Alice 仍對該數據庫記錄保持讀鎖。
-
只有在 Alice 的事務結束並且釋放了所有鎖之後,Bob 才能恢復其 UPDATE 操作。
-
Bob 的 UPDATE 語句將生成鎖升級,因此他先前獲取的讀取鎖將被排他鎖替換,這將防止其他事務獲取同一 post 記錄上的讀取或寫入鎖。
-
愛麗絲啓動了一個新事務,併發出了 SELECT FOR SHARE 針對同一 post 條目的讀取鎖獲取請求的查詢,但是由於鮑勃對該記錄擁有排他鎖,因此該語句被鎖管理器阻止。
-
提交 Bob 的事務後,將釋放他的所有鎖,並且可以恢復 Alice 的 SELECT 查詢。
嚴格的可序列化(可串行化、可線性化)
2PL 算法提供嚴格的可序列化性,這是涉及數據完整性的黃金標準。嚴格的可序列化性意味着結果既可序列化又可線性化。
如果兩個或多個事務的關聯讀取和寫入操作以某種結果等效於某種串行執行的方式交錯,則它們是可序列化的。例如,如果我們有兩個事務 A 和 B,只要結果是 A,B 或 B,A,則這兩個事務都是可序列化的。對於 N 個事務,結果必須等於 N! 事務排列之一。
但是,可串行性未考慮時間流。另一方面,線性化意味着基於時間的排序。例如,如果任何後續讀取將反映先前寫入操作所做的更改,則系統是可線性化的。有關 Lienearizbaility 的更多詳細信息,請查看本文。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/QKraTI82dzK8Up4V4IcMbw