<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 13.3\. 明確鎖定 PostgreSQL提供了多種鎖模式用于控制對表中數據的并發訪問。 這些模式可以用于在MVCC無法給出期望行為的場合。同樣, 大多數PostgreSQL命令自動施加恰當的鎖以保證被引用的表在命令的執行過程中不會以一種不兼容的方式被刪除或者修改。 比如,在存在其它并發操作的時候,`TRUNCATE`是不能在同一個表上面執行的 要檢查數據庫服務器里所有當前正在被持有的鎖, 可以使用[`pg_locks`](#calibre_link-723)系統視圖。 有關監控鎖管理器子系統狀態的更多信息,請參考章[Chapter 27](#calibre_link-1179)。 ## 13.3.1\. 表級鎖 下面的列表顯示了可用的鎖模式和它們被PostgreSQL自動使用的場合。 你也可以用[LOCK](#calibre_link-1151)命令明確獲取這些鎖。請注意所有這些鎖模式都是表級鎖, 即使它們的名字包含"row"單詞(這些名稱是歷史遺產)。從某種角度而言, 這些名字反應了每種鎖模式的典型用法— 但是語意卻都是一樣的。 兩種鎖模式之間真正的區別是它們有著不同的沖突鎖集合(參見[Table 13-2](#calibre_link-1180))。 兩個事務在同一時刻不能在同一個表上持有相互沖突的鎖。不過,一個事務決不會和自身沖突。比如,它可以在一個表上請求`ACCESS EXCLUSIVE`然后接著請求 `ACCESS SHARE`。 非沖突鎖模式可以被許多事務同時持有。請特別注意有些鎖模式是自沖突的(比如,在任意時刻`ACCESS EXCLUSIVE`模式就不能夠被多個事務擁有), 但其它鎖模式都不是自沖突的(比如,`ACCESS SHARE`可以被多個事務持有)。 **表級鎖模式** `ACCESS SHARE` 只與`ACCESS EXCLUSIVE`沖突。 `SELECT`命令在被引用的表上請求一個這種鎖。通常, 任何只_讀取_表而不修改它的命令都請求這種鎖模式。 `ROW SHARE` 與`EXCLUSIVE`和`ACCESS EXCLUSIVE`鎖模式沖突。 `SELECT FOR UPDATE`和`SELECT FOR SHARE`命令在目標表上需要一個這樣模式的鎖 (加上在所有被引用但沒有`ACCESS SHARE`的表上的`FOR UPDATE/FOR SHARE`鎖)。 `ROW EXCLUSIVE` 與`SHARE`, `SHARE ROW EXCLUSIVE`, `EXCLUSIVE`和 `ACCESS EXCLUSIVE`鎖模式沖突。 `UPDATE`,`DELETE`和`INSERT`命令自動請求這個鎖模式(加上所有其它被引用的表上的`ACCESS SHARE`鎖)。 通常,這種鎖將被任何_修改表中數據_的查詢請求。 `SHARE UPDATE EXCLUSIVE` 與`SHARE UPDATE EXCLUSIVE`, `SHARE`, `SHARE ROW EXCLUSIVE`, `EXCLUSIVE`和 `ACCESS EXCLUSIVE`鎖模式沖突。 這個模式保護一個表不被并發模式改變和`VACUUM`。 `VACUUM`(不帶`FULL`選項), `ANALYZE`, `CREATE INDEX CONCURRENTLY`和`ALTER TABLE`請求這樣的鎖。 `SHARE` 與`ROW EXCLUSIVE`, `SHARE UPDATE EXCLUSIVE`, `SHARE ROW EXCLUSIVE`, `EXCLUSIVE`和 `ACCESS EXCLUSIVE`鎖模式沖突。 這個模式避免表的并發數據修改。 `CREATE INDEX`(不帶`CONCURRENTLY`選項)語句要求這樣的鎖模式。 `SHARE ROW EXCLUSIVE` 與`ROW EXCLUSIVE`, `SHARE UPDATE EXCLUSIVE`, `SHARE`, `SHARE ROW EXCLUSIVE`, `EXCLUSIVE`和 `ACCESS EXCLUSIVE`鎖模式沖突。這個模式避免表的并發數據修改。 并且是自我排斥的,因此每次只有一個會話可以擁有它。 任何PostgreSQL命令都不會自動請求這個鎖模式。 `EXCLUSIVE` 與 `ROW SHARE`, `ROW EXCLUSIVE`, `SHARE UPDATE EXCLUSIVE`, `SHARE`, `SHARE ROW EXCLUSIVE`, `EXCLUSIVE`和 `ACCESS EXCLUSIVE`鎖模式沖突。這個模式只允許并發`ACCESS SHARE`鎖,也就是說, 只有對表的讀動作可以和持有這個鎖模式的事務并發執行。 任何PostgreSQL命令都不會在用戶表上自動請求這個鎖模式。 `ACCESS EXCLUSIVE` 與所有模式沖突(`ACCESS SHARE`, `ROW SHARE`, `ROW EXCLUSIVE`, `SHARE UPDATE EXCLUSIVE`, `SHARE`, `SHARE ROW EXCLUSIVE`, `EXCLUSIVE`和 `ACCESS EXCLUSIVE`)。這個模式保證其所有者(事務)是可以訪問該表的唯一事務。 `ALTER TABLE`, `DROP TABLE`, `TRUNCATE`, `REINDEX`, `CLUSTER`和`VACUUM FULL`命令要求這樣的鎖。 在`LOCK TABLE`命令沒有明確聲明需要的鎖模式時,它是缺省鎖模式。 > **Tip:** 只有`ACCESS EXCLUSIVE`阻塞`SELECT` (不包含`FOR UPDATE/SHARE`語句)。 一旦請求已獲得某種鎖,那么該鎖模式將持續到事務結束。但是如果在建立保存點之后才獲得鎖, 那么在回滾到這個保存點的時候將立即釋放所有該保存點之后獲得的鎖。這與`ROLLBACK`取消所有保存點之后對表的影響的原則一致。 同樣的原則也適用于PL/pgSQL異常塊中獲得的鎖: 一個跳出塊的錯誤將釋放在塊中獲得的鎖。 **Table 13-2\. 沖突鎖模式** | Requested Lock Mode | Current Lock Mode | | --- | --- | | ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE | | --- | --- | --- | --- | --- | --- | --- | --- | | ACCESS SHARE | X | | ROW SHARE | X | X | | ROW EXCLUSIVE | X | X | X | X | | SHARE UPDATE EXCLUSIVE | X | X | X | X | X | | SHARE | X | X | X | X | X | | SHARE ROW EXCLUSIVE | X | X | X | X | X | X | | EXCLUSIVE | X | X | X | X | X | X | X | | ACCESS EXCLUSIVE | X | X | X | X | X | X | X | X | ## 13.3.2\. 行級鎖 除了表級鎖以外,還有行級鎖,他們可以是排他的或者是共享的。特定行上的排他行級鎖是在行被更新的時候自動請求的。 該鎖一直保持到事務提交或者回滾。行級鎖不影響對數據的查詢,它們只阻塞對_同一行的寫入_。 要在不修改某行的前提下請求該行上的一個排他行級鎖,用`SELECT FOR UPDATE`選取該行。 請注意一旦我們請求了特定的行級鎖,那么該事務就可以多次對該行進行更新而不用擔心沖突。 要在某行上請求一個共享的行級鎖,用`SELECT FOR SHARE`選取該行。 一個共享鎖并不阻止其它事務請求同一個共享的鎖。不過,其它事務不允許更新、刪除、 或者排他鎖住持有共享鎖的行。任何這么做的企圖都將被阻塞并等待共享鎖的釋放。 PostgreSQL不會在內存里保存任何關于已修改行的信息,因此對一次鎖定的行數沒有限制。 不過,鎖住一行會導致一次磁盤寫;因為`SELECT FOR UPDATE`將修改選中的行以標記它們被鎖住了, 所以會導致磁盤寫。 除了表級別和行級別的鎖以外,頁面級別的共享/排他鎖也用于控制共享緩沖池中表頁面的讀/寫。 這些鎖在抓取或者更新一行后馬上被釋放。應用程序員通常不需要關心頁級鎖, 我們在這里提到它們只是為了完整。 ## 13.3.3\. 死鎖 明確鎖定的使用可能會增加_死鎖_的可能性,死鎖是指兩個(或多個)事務相互持有對方期待的鎖。 比如,如果事務 1 在表 A 上持有一個排他鎖,同時試圖請求一個在表 B 上的排他鎖, 而事務 2 已經持有表 B 的排他鎖,而卻正在請求在表 A 上的一個排他鎖, 那么兩個事務就都不能執行。 PostgreSQL能夠自動偵測死鎖條件并且會通過退出其中一個事務從而允許其它事務完成來解決這個問題。 具體哪個事務會被退出是很難預計的,而且也不應該依靠這樣的預計。 要注意的是死鎖也可能會因為行級鎖而發生(即使是沒有使用明確的鎖定)。 考慮如下情況,兩個并發事務在修改一個表。第一個事務執行了: ``` UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 11111; ``` 這樣就在指定帳號的行上請求了一個行級鎖。然后,第二個事務執行: ``` UPDATE accounts SET balance = balance + 100.00 WHERE acctnum = 22222; UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 11111; ``` 第一個`UPDATE`語句成功地在指定行上請求到了一個行級鎖,因此它成功更新了該行。 但是第二個`UPDATE`語句發現它試圖更新的行已經被鎖住了,因此它等待持有該鎖的事務結束。 事務二現在就在等待事務一結束,然后再繼續執行。現在,事務一執行: ``` UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; ``` 事務一企圖在指定行上請求一個行級鎖,但是它得不到:事務二已經持有這樣的鎖了。 所以它等待事務二完成。因此,事務一被事務二阻塞住了,而事務二也被事務一阻塞住了: 這就是一個死鎖條件。PostgreSQL將偵測這樣的條件并退出其中一個事務。 防止死鎖的最好方法通常是保證所有使用一個數據庫的應用都以一致的順序在多個對象上請求鎖定。 在上面的例子里,如果兩個事務以同樣的順序更新那些行,那么就不會發生死鎖。 我們也要保證在一個對象上請求的第一個鎖是該對象需要的最高的鎖模式。 如果我們無法提前核實這些問題,那么我們可以通過在現場重新嘗試因死鎖而退出的事務的方法來處理。 只要沒有檢測到死鎖條件,事務將一直等待表級鎖或行級鎖的釋放。 這意味著一個事務持續的時間太長不是什么好事(比如等待用戶輸入)。 ## 13.3.4\. 咨詢鎖 PostgreSQL允許創建由應用定義其含義的鎖。這種鎖被稱為_咨詢鎖_, 因為系統并不強迫其使用— 而是由應用來保證其被恰當的使用。 咨詢鎖可用于 MVCC 難以實現的鎖定策略。 比如,咨詢鎖一般用于模擬常見于"平面文件"數據管理系統的悲觀鎖策略。 雖然可以用存儲在表中的一個特定標志達到同樣的目的,但是使用咨詢鎖更快,還可以避免表臃腫, 更可以在會話結束的時候由系統自動執行清理工作。 PostgreSQL中有兩種方式可以獲得咨詢鎖:會話級別或者事務級別。 咨詢鎖一旦被持有就將持續到被明確釋放或會話結束。 不同于各種標準的鎖,咨詢鎖并不考慮事務的語意: 在一個被回滾的事務中獲得的咨詢鎖并不會被自動釋放,同樣的, 在一個失敗的事務中釋放的咨詢鎖仍將保持釋放。同一個咨詢鎖可以被它自己的進程多次獲得: 對于每一個鎖定請求必須有一個相應的釋放請求,這樣才能最終真正釋放該鎖。 另一方面,事務級別的鎖請求,表現得更像普通鎖請求:他們結束事務時自動釋放, 并且沒有明確的解鎖操作。這種行為通常比咨詢鎖的短期使用會話級別行為更方便。 會話級別和事務級別鎖請求為相同的咨詢鎖標識符將以預期方式互相阻止。 如果某個會話已經持有一個咨詢鎖,那么對該鎖的多次鎖定請求將總會成功,即使其它會話正在等候該鎖的釋放也是如此。 不管是否持有已存在鎖,并且新的要求是會話級別或者事務級別,這個語句是真的。 與PostgreSQL中其它鎖一樣, 可以在[`pg_locks`](#calibre_link-723)系統視圖中查看當前被會話持有的所有咨詢鎖。 咨詢鎖和規則鎖存儲在共享內存池中,其中大小由[max_locks_per_transaction](#calibre_link-642)和 [max_connections](#calibre_link-441)配置參數決定。 千萬不要耗盡這些內存,否則服務器將不能再獲取任何新鎖。 因此服務器可以獲得的咨詢鎖數量是有限的,根據服務器的配置不同, 這個限制可能是幾萬到幾十萬個。 在某些使用咨詢鎖方法的特定情況下,特別是查詢包括明確的排序或`LIMIT`子句的時候, 由于 SQL 表達式求值順序的影響,必須注意控制咨詢鎖的獲取。例如: ``` SELECT pg_advisory_lock(id) FROM foo WHERE id = 12345; -- ok SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100; -- danger! SELECT pg_advisory_lock(q.id) FROM ( SELECT id FROM foo WHERE id > 12345 LIMIT 100 ) q; -- ok ``` 在上述查詢中,第二種形式是危險的,因為`LIMIT` 并不一定在鎖定函數執行之前被應用。 這可能導致獲得某些應用不期望的鎖,并因此在會話結束之前無法釋放。從應用的角度來看, 這樣的鎖將被掛起,雖然它們仍然在`pg_locks`中可見。 用于操作咨詢鎖的函數在[Section 9.26.8](#calibre_link-1181)中描述。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看