共計(jì) 1549 個(gè)字符,預(yù)計(jì)需要花費(fèi) 4 分鐘才能閱讀完成。
這篇文章主要為大家展示了“PostgreSQL MVCC 源碼的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓丸趣 TV 小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“PostgreSQL MVCC 源碼的示例分析”這篇文章吧。
MVCC 對(duì)每一個(gè) DBA 來講,都不陌生,即多版本控制(Multi-Version-Control)。正因?yàn)閿?shù)據(jù)有了多個(gè)版本,才實(shí)現(xiàn)了讀和寫在一定程度上的分離,提高數(shù)據(jù)庫(kù)每秒處理查詢的能力(QPS)。
用戶發(fā)起的普通查詢請(qǐng)求(不包含 select … for update 語(yǔ)句),并不堵塞 DML 事務(wù)。在 Read Commit 事務(wù)隔離級(jí)別時(shí),查詢請(qǐng)求只讀取查詢請(qǐng)求之前已經(jīng)提交的事務(wù)的數(shù)據(jù)更改,對(duì)當(dāng)前版本的數(shù)據(jù)并不影響;
而 DML 語(yǔ)句,會(huì)操作當(dāng)前版本。因此做到了讀寫分離的目的,提高數(shù)據(jù)庫(kù)并發(fā)能力。
不同的數(shù)據(jù)庫(kù),實(shí)現(xiàn) MVCC 的方法不同。Oracle 和 MySQL Innodb 存儲(chǔ)引擎類似的使用 undo 來實(shí)現(xiàn)。
對(duì)于 PostgreSQL 數(shù)據(jù)庫(kù)來講,他沒有 undo,那么,PG 又是怎么來實(shí)現(xiàn)他自己的 MVCC 呢?又有那些優(yōu)缺點(diǎn)呢?
PG 用 copy tuple 和 tuple 的 xmin,xmax,cmin,cmax 等標(biāo)記來實(shí)現(xiàn)多版本。
xmin:在創(chuàng)建記錄 (tuple) 時(shí),記錄此時(shí),后面每次 update 也會(huì)更新。
xmax: 在刪除 tuple 或者 lock 時(shí),記錄此時(shí);如果記錄沒有被刪除,那么此時(shí)為 0。
cmin 和 cmax:主要為標(biāo)識(shí)在同一個(gè)事務(wù)中多個(gè)語(yǔ)句命令的序列值。用于同一個(gè)事務(wù)中實(shí)現(xiàn)版本可見性判斷。
1. 下面我們先來看一下 xmin 和 xmax 的變化:
從上圖可以看出,4 條記錄的 xmin 是一樣的,都是“390689”,這說明是在同一個(gè)事務(wù)中創(chuàng)建的。另外 xmax 都為“0”,說明都沒有被刪除。cmin 和 cmax 都是 1,說明是同一個(gè)命令創(chuàng)建的。
接下來,我們 update 一下 id 為 1 的記錄,看發(fā)生什么情況:
update 之后,并沒有提交,重新開起另外一個(gè)窗口,查詢:
我們看到,ID 為 1 的記錄,只有 xmin 沒有變化,其它三個(gè)值都發(fā)生了變化,其中 xmax 變成了”390691”。
然后我把事務(wù)提交掉,再在新窗口中查詢:
我們看到,提交后,ID 為 1 的記錄,xmin 變?yōu)椤?90691”,xmin 增加了 1;而 xmax 變成了 0。
從上面的案例中,我們從表面上可以看出,xmin 增加了。但是事實(shí)上,PostgreSQL 在底層所做的事情,遠(yuǎn)比這個(gè)要多。底層已經(jīng)生成了一個(gè)新版本的 tuple,新版本 tuple 的 xmin 等于老版本的 xmax。
詳細(xì)的 internal,我后面再展開講。
2. 我們?cè)賮砜匆幌?cmin 和 cmax 的變化:
我起一個(gè)事務(wù),包含兩條 update,一條 update ID 值為 2 的記錄,一條 insert ID 值為 3 的記錄:
事務(wù)“390694”中,cmin 和 cmax 的值,依次遞增。從目前來看 cmin 和 cmax 實(shí)際上是同一個(gè) field。
源碼定義如下,用 union 實(shí)現(xiàn)了 CommandId,是一個(gè) combo command id。
因此,從上面的例子來看,PostgreSQL 的 mvcc 實(shí)現(xiàn)是比較簡(jiǎn)單的。只需要通過對(duì)比 tuple header 中 xmin,xmax,cmin,cmax 與當(dāng)前的 xid,就可以得到在 scan tuple 時(shí),此 tuple 對(duì)于當(dāng)前查詢的可視性。
可見性判斷邏輯:
但是也帶來了另外一個(gè)問題:就是在沒有 undo 的情況下,會(huì)導(dǎo)致空間的增長(zhǎng)。因此 PostgreSQL 引入了 vacumm 后臺(tái)進(jìn)程,來定期清理這些 DEAD tuple。
以上是“PostgreSQL MVCC 源碼的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道!