摘要:分析對于的自身事務的一定是不可見對于自身事務的并且已經提交的事務可見除外對于第一條規則很好判斷在自身事務之后的動作一定是看不見的。第二條規則困難一些需要判斷一個事務是否提交可能還需判斷是否是。
Postgresql MVCC Postgresql的隱藏列
tableoid
是表對象的一個唯一標識符,可以和pg_class中的oid聯合起來查看
xmin
是插入的事務標識符,是用來標識不同事務下的一個版本控制
xmax
是刪除更新的事務標識符,如果該值不為0,則說明該行數據當前還未提交或回滾
cmin
插入事務的命令標識符,從0開始
cmax
刪除事務的命令標識符,或者為0
ctid
是每行數據在表中的一個物理位置標識符
下面舉例說明:
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 是插入數據的事務id xmax: 0 表示已經提交了 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
首先打開兩個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) 從上面的數據可以看出當數據庫做一個更新操作時,并不是將老的數據刪除,再將新的數據覆蓋上去,相反它會把老的數據做一個標記隔離出去,然后再新增新的數據作為一個新的版本 現在看另一個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) 從上面的數據逆推當Update時postgres 至少做三個動作 1. copy olddata to newplace 2. update data 3. add new transaction id to old data xmax postgresq Delete 會更簡單一些只需要在tuple 上做一個標記. 既然postgres不會直接在olddata上修改,又是如何對這些tuple做隔離的呢? 簡而言之postgres 如何判斷這些tuple 是否對一個事務可見。 分析: 1. 對于tuple 的 xmin > 自身事務id 的row 一定是不可見 2. 對于tuple xmin < 自身事務id 的row并且已經提交的事務可見(deleted tuple 除外) 對于第一條規則很好判斷(在自身事務之后的動作一定是看不見的)。 第二條規則困難一些需要判斷一個事務是否提交,(可能還需判斷tuple是否是deleted。因為postgresql vacuum 是異步刪除deleted tuple) 對于這個問題postgres在tuple的header 里加入一個屬性 t_infomask 用于標記transaction的狀態.
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 文章實在太好了
Postgres Hint Bits
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/38954.html
摘要:關系型數據庫中的事務管理詳解并發控制與事務日志數據庫系統的萌芽出現于年代。并發控制并發控制旨在針對數據庫中對事務并行的場景,保證中的一致性與隔離性。絕大部分數據庫會采用鎖或者數據版本控制的方式來處理并發控制問題。 本文節選自:關系型數據庫理論 https://url.wx-coder.cn/DJNQn ,涉及引用/整理的文章列舉在了 Database-List。 showImg(htt...
摘要:關系型數據庫中的事務管理詳解并發控制與事務日志數據庫系統的萌芽出現于年代。并發控制并發控制旨在針對數據庫中對事務并行的場景,保證中的一致性與隔離性。絕大部分數據庫會采用鎖或者數據版本控制的方式來處理并發控制問題。 本文節選自:關系型數據庫理論 https://url.wx-coder.cn/DJNQn ,涉及引用/整理的文章列舉在了 Database-List。 showImg(htt...
閱讀 6866·2021-09-22 15:36
閱讀 5687·2021-09-02 10:20
閱讀 1869·2019-08-30 15:44
閱讀 2653·2019-08-29 14:06
閱讀 1155·2019-08-29 11:17
閱讀 1586·2019-08-26 14:05
閱讀 3093·2019-08-26 13:50
閱讀 1551·2019-08-26 10:26