摘要:分析對(duì)于的自身事務(wù)的一定是不可見(jiàn)對(duì)于自身事務(wù)的并且已經(jīng)提交的事務(wù)可見(jiàn)除外對(duì)于第一條規(guī)則很好判斷在自身事務(wù)之后的動(dòng)作一定是看不見(jiàn)的。第二條規(guī)則困難一些需要判斷一個(gè)事務(wù)是否提交可能還需判斷是否是。
Postgresql MVCC Postgresql的隱藏列
tableoid
是表對(duì)象的一個(gè)唯一標(biāo)識(shí)符,可以和pg_class中的oid聯(lián)合起來(lái)查看
xmin
是插入的事務(wù)標(biāo)識(shí)符,是用來(lái)標(biāo)識(shí)不同事務(wù)下的一個(gè)版本控制
xmax
是刪除更新的事務(wù)標(biāo)識(shí)符,如果該值不為0,則說(shuō)明該行數(shù)據(jù)當(dāng)前還未提交或回滾
cmin
插入事務(wù)的命令標(biāo)識(shí)符,從0開始
cmax
刪除事務(wù)的命令標(biāo)識(shí)符,或者為0
ctid
是每行數(shù)據(jù)在表中的一個(gè)物理位置標(biāo)識(shí)符
下面舉例說(shuō)明:
t1=# create table test (id integer, value text); CREATE TABLE t1=# insert into test values (1, "a"), (2, "aa"), (3, "aaa"); INSERT 0 3 t1=# select cmin,cmax,xmin,xmax,ctid, * from test; cmin | cmax | xmin | xmax | ctid | id | value ------+------+----------+------+-------+----+------- 0 | 0 | 75066031 | 0 | (0,1) | 1 | a 0 | 0 | 75066031 | 0 | (0,2) | 2 | aa 0 | 0 | 75066031 | 0 | (0,3) | 3 | aaa (3 rows) xmin: 75066031 是插入數(shù)據(jù)的事務(wù)id xmax: 0 表示已經(jīng)提交了 ctid: (0, 1), (0, 2), (0, 3)是tuple 所在table中的位置 t1=# begin; BEGIN t1=# select tableoid from test; tableoid ---------- 96972 96972 96972 (3 rows) t1=# insert into test values (4, "b"); INSERT 0 1 t1=# insert into test values (5, "bb"); INSERT 0 1 t1=# insert into test values (6, "bbb"); INSERT 0 1 t1=# select cmin,cmax,xmin,xmax,ctid, * from test; cmin | cmax | xmin | xmax | ctid | id | value ------+------+----------+------+-------+----+------- 0 | 0 | 75066031 | 0 | (0,1) | 1 | a 0 | 0 | 75066031 | 0 | (0,2) | 2 | aa 0 | 0 | 75066031 | 0 | (0,3) | 3 | aaa 0 | 0 | 75066040 | 0 | (0,4) | 4 | b 1 | 1 | 75066040 | 0 | (0,5) | 5 | bb 2 | 2 | 75066040 | 0 | (0,6) | 6 | bbb (6 rows) t1=# commit; COMMIT tableoid: 是表的oid
首先打開兩個(gè)psql t1=# begin; BEGIN t1=# select cmin,cmax,xmin,xmax,ctid, * from test; cmin | cmax | xmin | xmax | ctid | id | value ------+------+----------+------+-------+----+------- 0 | 0 | 75066031 | 0 | (0,1) | 1 | a 0 | 0 | 75066031 | 0 | (0,2) | 2 | aa 0 | 0 | 75066031 | 0 | (0,3) | 3 | aaa 0 | 0 | 75066040 | 0 | (0,4) | 4 | b 1 | 1 | 75066040 | 0 | (0,5) | 5 | bb 2 | 2 | 75066040 | 0 | (0,6) | 6 | bbb (6 rows) t1=# update test set value = "c" where id = 4; UPDATE 1 t1=# select cmin,cmax,xmin,xmax,ctid, * from test; cmin | cmax | xmin | xmax | ctid | id | value ------+------+----------+------+-------+----+------- 0 | 0 | 75066031 | 0 | (0,1) | 1 | a 0 | 0 | 75066031 | 0 | (0,2) | 2 | aa 0 | 0 | 75066031 | 0 | (0,3) | 3 | aaa 1 | 1 | 75066040 | 0 | (0,5) | 5 | bb 2 | 2 | 75066040 | 0 | (0,6) | 6 | bbb 0 | 0 | 75066045 | 0 | (0,7) | 4 | c (6 rows) t1=# select txid_current(); txid_current -------------- 75066045 (1 row) 從上面的數(shù)據(jù)可以看出當(dāng)數(shù)據(jù)庫(kù)做一個(gè)更新操作時(shí),并不是將老的數(shù)據(jù)刪除,再將新的數(shù)據(jù)覆蓋上去,相反它會(huì)把老的數(shù)據(jù)做一個(gè)標(biāo)記隔離出去,然后再新增新的數(shù)據(jù)作為一個(gè)新的版本 現(xiàn)在看另一個(gè)psql t1=# begin; BEGIN t1=# select cmin,cmax,xmin,xmax,ctid, * from test; cmin | cmax | xmin | xmax | ctid | id | value ------+------+----------+----------+-------+----+------- 0 | 0 | 75066031 | 0 | (0,1) | 1 | a 0 | 0 | 75066031 | 0 | (0,2) | 2 | aa 0 | 0 | 75066031 | 0 | (0,3) | 3 | aaa 0 | 0 | 75066040 | 75066045 | (0,4) | 4 | b 1 | 1 | 75066040 | 0 | (0,5) | 5 | bb 2 | 2 | 75066040 | 0 | (0,6) | 6 | bbb (6 rows) 從上面的數(shù)據(jù)逆推當(dāng)Update時(shí)postgres 至少做三個(gè)動(dòng)作 1. copy olddata to newplace 2. update data 3. add new transaction id to old data xmax postgresq Delete 會(huì)更簡(jiǎn)單一些只需要在tuple 上做一個(gè)標(biāo)記. 既然postgres不會(huì)直接在olddata上修改,又是如何對(duì)這些tuple做隔離的呢? 簡(jiǎn)而言之postgres 如何判斷這些tuple 是否對(duì)一個(gè)事務(wù)可見(jiàn)。 分析: 1. 對(duì)于tuple 的 xmin > 自身事務(wù)id 的row 一定是不可見(jiàn) 2. 對(duì)于tuple xmin < 自身事務(wù)id 的row并且已經(jīng)提交的事務(wù)可見(jiàn)(deleted tuple 除外) 對(duì)于第一條規(guī)則很好判斷(在自身事務(wù)之后的動(dòng)作一定是看不見(jiàn)的)。 第二條規(guī)則困難一些需要判斷一個(gè)事務(wù)是否提交,(可能還需判斷tuple是否是deleted。因?yàn)閜ostgresql vacuum 是異步刪除deleted tuple) 對(duì)于這個(gè)問(wèn)題postgres在tuple的header 里加入一個(gè)屬性 t_infomask 用于標(biāo)記transaction的狀態(tài).
select * from pg_available_extensions; create extension pageinspect; t1=# begin; BEGIN t1=# select cmin,cmax,xmin,xmax,ctid, * from test; cmin | cmax | xmin | xmax | ctid | id | value ------+------+----------+------+-------+----+------- 0 | 0 | 75066031 | 0 | (0,1) | 1 | a 0 | 0 | 75066031 | 0 | (0,2) | 2 | aa 0 | 0 | 75066031 | 0 | (0,3) | 3 | aaa 1 | 1 | 75066040 | 0 | (0,4) | 5 | bb 2 | 2 | 75066040 | 0 | (0,5) | 6 | bbb 0 | 0 | 75066110 | 0 | (0,6) | 4 | b (6 rows) t1=# SELECT * FROM heap_page_items(get_raw_page("test", 0)); lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid ----+--------+----------+--------+----------+--------+----------+--------+-------------+------------+--------+--------+------- 1 | 8160 | 1 | 30 | 75066031 | 0 | 0 | (0,1) | 2 | 2818 | 24 | | 2 | 8128 | 1 | 31 | 75066031 | 0 | 0 | (0,2) | 2 | 2818 | 24 | | 3 | 8096 | 1 | 32 | 75066031 | 0 | 0 | (0,3) | 2 | 2818 | 24 | | 4 | 8064 | 1 | 31 | 75066040 | 0 | 1 | (0,4) | 2 | 2818 | 24 | | 5 | 8032 | 1 | 32 | 75066040 | 0 | 2 | (0,5) | 2 | 2818 | 24 | | 6 | 8000 | 1 | 30 | 75066110 | 0 | 0 | (0,6) | 2 | 11010 | 24 | | (6 rows) t1=# update test set value = "c" where id = 4; UPDATE 1 t1=# SELECT * FROM heap_page_items(get_raw_page("test", 0)); lp | lp_off | lp_flags | lp_len | t_xmin | t_xmax | t_field3 | t_ctid | t_infomask2 | t_infomask | t_hoff | t_bits | t_oid ----+--------+----------+--------+----------+----------+----------+--------+-------------+------------+--------+--------+------- 1 | 8160 | 1 | 30 | 75066031 | 0 | 0 | (0,1) | 2 | 2818 | 24 | | 2 | 8128 | 1 | 31 | 75066031 | 0 | 0 | (0,2) | 2 | 2818 | 24 | | 3 | 8096 | 1 | 32 | 75066031 | 0 | 0 | (0,3) | 2 | 2818 | 24 | | 4 | 8064 | 1 | 31 | 75066040 | 0 | 1 | (0,4) | 2 | 2818 | 24 | | 5 | 8032 | 1 | 32 | 75066040 | 0 | 2 | (0,5) | 2 | 2818 | 24 | | 6 | 8000 | 1 | 30 | 75066110 | 75066121 | 0 | (0,7) | 16386 | 8962 | 24 | | 7 | 7968 | 1 | 30 | 75066121 | 0 | 0 | (0,7) | 32770 | 10242 | 24 | | (7 rows) t1=# select cmin,cmax,xmin,xmax,ctid, * from test; cmin | cmax | xmin | xmax | ctid | id | value ------+------+----------+------+-------+----+------- 0 | 0 | 75066031 | 0 | (0,1) | 1 | a 0 | 0 | 75066031 | 0 | (0,2) | 2 | aa 0 | 0 | 75066031 | 0 | (0,3) | 3 | aaa 1 | 1 | 75066040 | 0 | (0,4) | 5 | bb 2 | 2 | 75066040 | 0 | (0,5) | 6 | bbb 0 | 0 | 75066121 | 0 | (0,7) | 4 | c (6 rows) t1=# select txid_current(); txid_current -------------- 75066121 (1 row)
Vacuum internals 文章實(shí)在太好了
Postgres Hint Bits
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/38954.html
摘要:關(guān)系型數(shù)據(jù)庫(kù)中的事務(wù)管理詳解并發(fā)控制與事務(wù)日志數(shù)據(jù)庫(kù)系統(tǒng)的萌芽出現(xiàn)于年代。并發(fā)控制并發(fā)控制旨在針對(duì)數(shù)據(jù)庫(kù)中對(duì)事務(wù)并行的場(chǎng)景,保證中的一致性與隔離性。絕大部分?jǐn)?shù)據(jù)庫(kù)會(huì)采用鎖或者數(shù)據(jù)版本控制的方式來(lái)處理并發(fā)控制問(wèn)題。 本文節(jié)選自:關(guān)系型數(shù)據(jù)庫(kù)理論 https://url.wx-coder.cn/DJNQn ,涉及引用/整理的文章列舉在了 Database-List。 showImg(htt...
摘要:關(guān)系型數(shù)據(jù)庫(kù)中的事務(wù)管理詳解并發(fā)控制與事務(wù)日志數(shù)據(jù)庫(kù)系統(tǒng)的萌芽出現(xiàn)于年代。并發(fā)控制并發(fā)控制旨在針對(duì)數(shù)據(jù)庫(kù)中對(duì)事務(wù)并行的場(chǎng)景,保證中的一致性與隔離性。絕大部分?jǐn)?shù)據(jù)庫(kù)會(huì)采用鎖或者數(shù)據(jù)版本控制的方式來(lái)處理并發(fā)控制問(wèn)題。 本文節(jié)選自:關(guān)系型數(shù)據(jù)庫(kù)理論 https://url.wx-coder.cn/DJNQn ,涉及引用/整理的文章列舉在了 Database-List。 showImg(htt...
閱讀 6949·2021-09-22 15:36
閱讀 5718·2021-09-02 10:20
閱讀 1884·2019-08-30 15:44
閱讀 2664·2019-08-29 14:06
閱讀 1163·2019-08-29 11:17
閱讀 1612·2019-08-26 14:05
閱讀 3108·2019-08-26 13:50
閱讀 1562·2019-08-26 10:26