暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PG 的 multixact是做什么的

原创 real 2020-01-12
6558

PG 中用tuple上的xmin,xmax 记录产生这一行的txid,与删除这一行的txid,并且用来实现锁机制, exclusive模式的锁只被一个事务持有,可以通过xmax中获取持有该锁的txid.很好理解. shared 模式的锁,是可以被多个事务共同持有的,怎么记录被哪些事务持有呢?
如何使用一个txid标识一组事务?Multixact就是做这个事的,用multixactid标识出一组事务。
引用《PostgreSQL数据库内核分析》中的一段描述

MULTIXACT日志是PostgreSQL系统用来记录组合事务ID的一种日志。由于PostgreSQL采用了多版本并发控制,因此同一个元组相关联的事务ID可能有多个,为了在加锁(行共享锁)的时侯统一操作,
PostgreSQL将与该元组相关联的多个事务ID组合起来用一个MultiXactID代替来管理。
image.png

实验验证

--创建测试表
postgres@test > create table t5(id int,name varchar(60));
CREATE TABLE
postgres@test > select * from t5;
 id |  name  
----+--------
  1 | test1
  2 | test2
  3 | test3
  4 | test4
  5 | test5
  6 | test6
  7 | test7
  8 | test8
  9 | test9
 10 | test10
(10 rows)
test=# 
--创建pageinspect扩展
create extension  pageinspect;
test=# \dx
                                  List of installed extensions
      Name       | Version |   Schema   |                      Description                      
-----------------+---------+------------+-------------------------------------------------------
 pageinspect     | 1.6     | public     | inspect the contents of database pages at a low level
 pg_freespacemap | 1.2     | public     | examine the free space map (FSM)
 plpgsql         | 1.0     | pg_catalog | PL/pgSQL procedural language
(3 rows)
postgres@test > select * from heap_page_items(get_raw_page('T5',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 |          t_data          
----+--------+----------+--------+---------+--------+----------+--------+-------------+------------+--------+--------+-------+--------------------------
  1 |   8152 |        1 |     34 | 3700709 |      0 |        0 | (0,1)  |           2 |       2306 |     24 | NULL   |  NULL | \x010000000d7465737431
  2 |   8112 |        1 |     34 | 3700709 |      0 |        0 | (0,2)  |           2 |       2306 |     24 | NULL   |  NULL | \x020000000d7465737432
  3 |   8072 |        1 |     34 | 3700709 |      0 |        0 | (0,3)  |           2 |       2306 |     24 | NULL   |  NULL | \x030000000d7465737433
  4 |   8032 |        1 |     34 | 3700709 |      0 |        0 | (0,4)  |           2 |       2306 |     24 | NULL   |  NULL | \x040000000d7465737434
  5 |   7992 |        1 |     34 | 3700709 |      0 |        0 | (0,5)  |           2 |       2306 |     24 | NULL   |  NULL | \x050000000d7465737435
  6 |   7952 |        1 |     34 | 3700709 |      0 |        0 | (0,6)  |           2 |       2306 |     24 | NULL   |  NULL | \x060000000d7465737436
  7 |   7912 |        1 |     34 | 3700709 |      0 |        0 | (0,7)  |           2 |       2306 |     24 | NULL   |  NULL | \x070000000d7465737437
  8 |   7872 |        1 |     34 | 3700709 |      0 |        0 | (0,8)  |           2 |       2306 |     24 | NULL   |  NULL | \x080000000d7465737438
  9 |   7832 |        1 |     34 | 3700709 |      0 |        0 | (0,9)  |           2 |       2306 |     24 | NULL   |  NULL | \x090000000d7465737439
 10 |   7792 |        1 |     35 | 3700709 |      0 |        0 | (0,10) |           2 |       2306 |     24 | NULL   |  NULL | \x0a0000000f746573743130
(10 rows)

---session 1 获取ID=1记录的shared锁
postgres@test > begin;
BEGIN
postgres@test > 
postgres@test > select pg_backend_pid(),txid_current();
 pg_backend_pid | txid_current 
----------------+--------------
          20827 |      3700712
(1 row)

postgres@test > 
postgres@test > select id,name from t5 where id=1 for share;
 id | name  
----+-------
  1 | test1
(1 row)
postgres@test > select * from heap_page_items(get_raw_page('T5',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 |          t_data          
----+--------+----------+--------+---------+---------+----------+--------+-------------+------------+--------+--------+-------+--------------------------
  1 |   8152 |        1 |     34 | 3700709 | 3700712 |        0 | (0,1)  |           2 |        466 |     24 | NULL   |  NULL | \x010000000d7465737431
  2 |   8112 |        1 |     34 | 3700709 |       0 |        0 | (0,2)  |           2 |       2306 |     24 | NULL   |  NULL | \x020000000d7465737432
  3 |   8072 |        1 |     34 | 3700709 |       0 |        0 | (0,3)  |           2 |       2306 |     24 | NULL   |  NULL | \x030000000d7465737433
  4 |   8032 |        1 |     34 | 3700709 |       0 |        0 | (0,4)  |           2 |       2306 |     24 | NULL   |  NULL | \x040000000d7465737434
  5 |   7992 |        1 |     34 | 3700709 |       0 |        0 | (0,5)  |           2 |       2306 |     24 | NULL   |  NULL | \x050000000d7465737435
  6 |   7952 |        1 |     34 | 3700709 |       0 |        0 | (0,6)  |           2 |       2306 |     24 | NULL   |  NULL | \x060000000d7465737436
  7 |   7912 |        1 |     34 | 3700709 |       0 |        0 | (0,7)  |           2 |       2306 |     24 | NULL   |  NULL | \x070000000d7465737437
  8 |   7872 |        1 |     34 | 3700709 |       0 |        0 | (0,8)  |           2 |       2306 |     24 | NULL   |  NULL | \x080000000d7465737438
  9 |   7832 |        1 |     34 | 3700709 |       0 |        0 | (0,9)  |           2 |       2306 |     24 | NULL   |  NULL | \x090000000d7465737439
 10 |   7792 |        1 |     35 | 3700709 |       0 |        0 | (0,10) |           2 |       2306 |     24 | NULL   |  NULL | \x0a0000000f746573743130
(10 rows)

---session 2 获取ID=1记录的shared锁
postgres@test > begin;
BEGIN
postgres@test > select pg_backend_pid(),txid_current();
 pg_backend_pid | txid_current 
----------------+--------------
            582 |      3700713
(1 row)

postgres@test > select id,name from t5 where id=1 for share;
 id | name  
----+-------
  1 | test1
(1 row)

postgres@test > select * from heap_page_items(get_raw_page('T5',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 |          t_data          
----+--------+----------+--------+---------+--------+----------+--------+-------------+------------+--------+--------+-------+--------------------------
  1 |   8152 |        1 |     34 | 3700709 |      1 |        0 | (0,1)  |           2 |       4562 |     24 | NULL   |  NULL | \x010000000d7465737431
  2 |   8112 |        1 |     34 | 3700709 |      0 |        0 | (0,2)  |           2 |       2306 |     24 | NULL   |  NULL | \x020000000d7465737432
  3 |   8072 |        1 |     34 | 3700709 |      0 |        0 | (0,3)  |           2 |       2306 |     24 | NULL   |  NULL | \x030000000d7465737433
  4 |   8032 |        1 |     34 | 3700709 |      0 |        0 | (0,4)  |           2 |       2306 |     24 | NULL   |  NULL | \x040000000d7465737434
  5 |   7992 |        1 |     34 | 3700709 |      0 |        0 | (0,5)  |           2 |       2306 |     24 | NULL   |  NULL | \x050000000d7465737435
  6 |   7952 |        1 |     34 | 3700709 |      0 |        0 | (0,6)  |           2 |       2306 |     24 | NULL   |  NULL | \x060000000d7465737436
  7 |   7912 |        1 |     34 | 3700709 |      0 |        0 | (0,7)  |           2 |       2306 |     24 | NULL   |  NULL | \x070000000d7465737437
  8 |   7872 |        1 |     34 | 3700709 |      0 |        0 | (0,8)  |           2 |       2306 |     24 | NULL   |  NULL | \x080000000d7465737438
  9 |   7832 |        1 |     34 | 3700709 |      0 |        0 | (0,9)  |           2 |       2306 |     24 | NULL   |  NULL | \x090000000d7465737439
 10 |   7792 |        1 |     35 | 3700709 |      0 |        0 | (0,10) |           2 |       2306 |     24 | NULL   |  NULL | \x0a0000000f746573743130
(10 rows)

复制

image.png

multixact日志结构

image.png

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
2人已赞赏
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论