濮阳杆衣贸易有限公司

主頁 > 知識庫 > 深入理解PostgreSQL的MVCC并發(fā)處理方式

深入理解PostgreSQL的MVCC并發(fā)處理方式

熱門標(biāo)簽:外呼線路資源屬于電信業(yè)務(wù)嗎 長沙電銷外呼防封卡是什么 內(nèi)蒙古營銷智能外呼系統(tǒng)哪個好 青白江400企業(yè)電話申請 智能外呼系統(tǒng)官網(wǎng) 河南電話外呼系統(tǒng)招商 小裙科技電銷機(jī)器人怎樣 crm外呼系統(tǒng)聯(lián)系方式 呼和浩特外呼系統(tǒng)原理是什么

Postgre數(shù)據(jù)庫的很大的賣點(diǎn)之一就是它處理并發(fā)的方式。我們的期望很簡單:讀永遠(yuǎn)不阻塞寫,反之亦然。Postgres通過一個叫做 多版本并發(fā)控制(MVCC) 的機(jī)制做到了這一點(diǎn)。這個技術(shù)并不是Postgres所特有的:還有好幾種數(shù)據(jù)庫都實現(xiàn)了不同形式的MVCC,包括 Oracle、Berkeley DB、CouchDB 等等 。當(dāng)你使用PostgreSQL來設(shè)計高并發(fā)的應(yīng)用時,理解它的MVCC是怎么實現(xiàn)的很重要。它事實上是復(fù)雜問題的一種非常優(yōu)雅和簡單的解法。

MVCC如何工作

在Postgres中,每一個事務(wù)都會得到一個被稱作為 XID 的事務(wù)ID。這里說的事務(wù)不僅僅是被 BEGIN - COMMIT 包裹的一組語句,還包括單條的insert、update或者delete語句。當(dāng)一個事務(wù)開始時,Postgrel遞增XID,然后把它賦給這個事務(wù)。Postgres還在系統(tǒng)里的每一行記錄上都存儲了事務(wù)相關(guān)的信息,這被用來判斷某一行記錄對于當(dāng)前事務(wù)是否可見。

舉個例子,當(dāng)你插入一行記錄時,Postgre會把當(dāng)前事務(wù)的XID存儲在這一行中并稱之為 xmin 。只有那些*已提交的而且 xmin` 比當(dāng)前事務(wù)的XID小的記錄對當(dāng)前事務(wù)才是可見的。這意味著,你可以開始一個新事務(wù)然后插入一行記錄,直到你提交( COMMIT )之前,你插入的這行記錄對其他事務(wù)永遠(yuǎn)都是不可見的。等到提交以后,其他后創(chuàng)建的新事務(wù)就可以看到這行新記錄了,因為他們滿足了 xmin XID 條件,而且創(chuàng)建哪一行記錄的事務(wù)也已經(jīng)完成。

對于 DELETE 和 UPDATE 來說,機(jī)制也是類似的,但不同的是對于它們Postgres使用叫做 xmax 的值來判斷數(shù)據(jù)的可見性。這幅圖展示了在兩個并發(fā)的插入/讀取數(shù)據(jù)的事務(wù)中,MVCC在事務(wù)隔離方面是怎么起作用的。

在下面的圖中,假設(shè)我們先執(zhí)行了這個建表語句:

復(fù)制代碼 代碼如下:
CREATE TABLE numbers (value int);

雖然 xmin 和 xmax 的值在日常使用中都是被隱藏的,但是你可以直接請求他們,Postgres會高興的把值給你:

復(fù)制代碼 代碼如下:
SELECT *, xmin, xmax FROM numbers;

獲取當(dāng)前事務(wù)的XID也很簡單:
復(fù)制代碼 代碼如下:
SELECT txid_current();

干凈利落!

我知道你現(xiàn)在在想:要是同時有兩個事務(wù)修改同一行數(shù)據(jù)會怎么樣?這就是事務(wù)隔離級別(transaction isolation levels)登場的時候了。Postgres支持兩個基本的模型來讓你控制應(yīng)該怎么處理這樣的情況。默認(rèn)情況下使用 讀已提交(READ COMMITTED) ,等待初始的事務(wù)完成后再讀取行記錄然后執(zhí)行語句。如果在等待的過程中記錄被修改了,它就從頭再來一遍。舉一個例子,當(dāng)你執(zhí)行一條帶有 WHERE 子句的 UPDATE 時, WHERE 子句會在最初的事務(wù)被提交后返回命中的記錄結(jié)果,如果這時 WHERE 子句的條件任然能得到滿足的話, UPDATE 才會被執(zhí)行。在下面這個例子中,兩個事務(wù)同時修改同一行記錄,最初的 UPDATE 語句導(dǎo)致第二個事務(wù)的 WHERE 不會返回任何記錄,因此第二個事務(wù)根本沒有修改到任何記錄:

如果你需要更好的控制這種行為,你可以把事務(wù)隔離級別設(shè)置為 可串行化(SERIALIZABLE) 。在這個策略下,上面的場景會直接失敗,因為它遵循這樣的規(guī)則:“如果我正在修改的行被其他事務(wù)修改過的話,就不再嘗試”,同時 Postgres會返回這樣的錯誤信息: 由于并發(fā)修改導(dǎo)致無法進(jìn)行串行訪問 。捕獲這個錯誤然后重試就是你的應(yīng)用需要去做的事情了,或者不重試直接放棄也行,如果那樣合理的話。

MVCC的缺點(diǎn)

現(xiàn)在你已經(jīng)知道MVCC和事務(wù)隔離是怎么工作了吧,你獲得了又一個工具用來解決這類問題: 可串行化事務(wù)隔離級別 遲早會派上用場。然而MVCC的優(yōu)點(diǎn)雖然很明顯但它也存在著一些缺點(diǎn)。

因為不同的事務(wù)會看到不同狀態(tài)的記錄,Postgres連那些可能過期的數(shù)據(jù)也需要保留著。這就是為什么 UPDATE 實際上是創(chuàng)建一行新紀(jì)錄而 DELETE 并不真正的刪除記錄(它只是簡單的把記錄標(biāo)記成已刪除然后設(shè)置XID的值)的原因。當(dāng)事務(wù)完成后,數(shù)據(jù)庫里會存在一些對以后的事務(wù)永遠(yuǎn)不可見的記錄。它們被稱作dead rows。MVCC帶來的另外一個問題是,事務(wù)的ID只能不斷的增加 - 它是32個bits,只能”支持大約四十億個事務(wù)。當(dāng)XID達(dá)到最大值后,它會變回零重新開始。突然間所有的記錄都變成了發(fā)生在將來的事務(wù)所產(chǎn)生的,所有的新事務(wù)都沒有辦法訪問到這些舊記錄了。

上面說到的dead row和事務(wù)XID循環(huán)問題都是通過執(zhí)行VACUUM命令(Postgres用來執(zhí)行清理操作的命令)來解決的。這應(yīng)該成為一個例行的維護(hù),所以Postgre自帶了auto_vacuum守護(hù)進(jìn)程會在一個可配置的周期內(nèi)自動執(zhí)行清理。留意點(diǎn)auto_vacuum很重要,因為在不同的部署環(huán)境中需要執(zhí)行清理的周期也會不同。你可以在Postgres的文檔里找到關(guān)于VACUUM的更多說明。

您可能感興趣的文章:
  • mysql多版本并發(fā)控制MVCC的實現(xiàn)
  • 關(guān)于Mysql隔離級別、鎖與MVCC介紹
  • SpringBoot中通過實現(xiàn)WebMvcConfigurer參數(shù)校驗的方法示例
  • Spring Boot配置接口WebMvcConfigurer的實現(xiàn)
  • 繼承WebMvcConfigurationSupport后自動配置不生效及如何配置攔截器
  • mysql 8.0.22.0 下載安裝配置方法圖文教程
  • Windows10下mysql 8.0.22 安裝配置方法圖文教程
  • mysql安裝圖解 mysql圖文安裝教程(詳細(xì)說明)
  • Can''''t connect to MySQL server on localhost (10061)解決方法
  • MySQL——修改root密碼的4種方法(以windows為例)
  • mysql中int、bigint、smallint 和 tinyint的區(qū)別詳細(xì)介紹
  • mysql 添加索引 mysql 如何創(chuàng)建索引
  • 超詳細(xì)mysql left join,right join,inner join用法分析
  • 淺析MySQL - MVCC

標(biāo)簽:安順 菏澤 舟山 黃石 楚雄 白山 池州 呼倫貝爾

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《深入理解PostgreSQL的MVCC并發(fā)處理方式》,本文關(guān)鍵詞  深入,理解,PostgreSQL,的,MVCC,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《深入理解PostgreSQL的MVCC并發(fā)處理方式》相關(guān)的同類信息!
  • 本頁收集關(guān)于深入理解PostgreSQL的MVCC并發(fā)處理方式的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    太谷县| 湖州市| 台安县| 淄博市| 灌云县| 黄浦区| 大同市| 镇沅| 水富县| 丰城市| 台湾省| 饶平县| 东光县| 嘉鱼县| 青河县| 莱阳市| 陆河县| 彰化市| 大同市| 南安市| 姜堰市| 上林县| 贵定县| 伊吾县| 从江县| 吴川市| 无为县| 揭西县| 富裕县| 江阴市| 麻阳| 简阳市| 定南县| 河北省| 巩义市| 繁峙县| 屯昌县| 缙云县| 始兴县| 舟曲县| 额济纳旗|