searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Postgresql Multixact实现(1)

2024-09-29 09:55:04
23
0

Postgresql支持对元组加锁,为了减少锁的内存占用,直接在xmax字段记录加锁的事务XID。
Postgresql元组锁有四种类型,分成不同的等级:
FOR UPDATE 对整个元组加排他锁;
FOR NO KEY UPDATE 对非关键列加排他锁;
FOR SHARE 对整个元组加共享锁;
FOR KEY SHARE 对关键列加共享锁;
元组锁的相容性视图如下:
Mode    FOR KEY SHARE    FOR SHARE    FOR NO KEY UPDATE    FOR UPDATE
FOR KEY SHARE                  Х
FOR SHARE                         Х     Х
FOR NO KEY UPDATE          Х     Х     Х
FOR UPDATE                       Х     Х     Х     Х
其中关键点是FOR NO KEY UPDATE和FOR KEY SHARE是可以兼容的。
当一个元组同时加多个互相兼容的锁时,PostgreSQL将与该元组相关联的多个事务ID组合起来,用一个MultiXactID记录到元组的xmax字段。

Multixact创建
举例如下:
Session 1
postgres=# begin;
BEGIN
postgres=# select *,xmax from course for share;
 cno |  cname  | credit | priorcourse | xmax
-----+---------+--------+-------------+------
 1   | Chinese |      5 |             |  633
 3   | English |      4 |             |  633
 2   | Physics |      5 |             |  633
postgres=# select txid_current();
 txid_current
--------------
          633
(1 row)

Session 2
postgres=# begin;
BEGIN
postgres=# select *,xmax from course for share;
 cno |  cname  | credit | priorcourse | xmax
-----+---------+--------+-------------+------
 1   | Chinese |      5 |             |  633
 3   | English |      4 |             |  633
 2   | Physics |      5 |             |  633
(3 rows)

postgres=# select txid_current();
 txid_current
--------------
          634
(1 row)

在compute_new_xmax_infomask函数
Session1的事务已经在xmax字段记录了自己的事务XID,因此会进入TransactionIdIsInProgress(xmax)分支,最终调用MultiXactIdCreate函数创建出一个multi_xact_id = 5。
由于加锁的tuple总共有3个元组,为了避免创建多个multi_xact_id,每个事务会创建一个mcache,当需要创建一个新的multi_xact_id,先遍历mcache中每个组合事务,比对组合事务中的每个成员。如果有完全相同的成员,直接复用已有的multi_xact_id=5。

Session 3
postgres=# select *,xmax from course;
 cno |  cname  | credit | priorcourse | xmax
-----+---------+--------+-------------+------
 1   | Chinese |      5 |             |    5
 3   | English |      4 |             |    5
 2   | Physics |      5 |             |    5

Multixact等待
Session 4
postgres=# begin;
BEGIN
postgres=# select * from course for update;

Session4
Do_MultiXactIdWait
对multixactId成员,循环调用XactLockTableWait,直到所有的加锁事务成员都已经提交或者回滚,才能尝试对元组加update锁。

0条评论
0 / 1000
吴****奇
3文章数
0粉丝数
吴****奇
3 文章 | 0 粉丝
吴****奇
3文章数
0粉丝数
吴****奇
3 文章 | 0 粉丝
原创

Postgresql Multixact实现(1)

2024-09-29 09:55:04
23
0

Postgresql支持对元组加锁,为了减少锁的内存占用,直接在xmax字段记录加锁的事务XID。
Postgresql元组锁有四种类型,分成不同的等级:
FOR UPDATE 对整个元组加排他锁;
FOR NO KEY UPDATE 对非关键列加排他锁;
FOR SHARE 对整个元组加共享锁;
FOR KEY SHARE 对关键列加共享锁;
元组锁的相容性视图如下:
Mode    FOR KEY SHARE    FOR SHARE    FOR NO KEY UPDATE    FOR UPDATE
FOR KEY SHARE                  Х
FOR SHARE                         Х     Х
FOR NO KEY UPDATE          Х     Х     Х
FOR UPDATE                       Х     Х     Х     Х
其中关键点是FOR NO KEY UPDATE和FOR KEY SHARE是可以兼容的。
当一个元组同时加多个互相兼容的锁时,PostgreSQL将与该元组相关联的多个事务ID组合起来,用一个MultiXactID记录到元组的xmax字段。

Multixact创建
举例如下:
Session 1
postgres=# begin;
BEGIN
postgres=# select *,xmax from course for share;
 cno |  cname  | credit | priorcourse | xmax
-----+---------+--------+-------------+------
 1   | Chinese |      5 |             |  633
 3   | English |      4 |             |  633
 2   | Physics |      5 |             |  633
postgres=# select txid_current();
 txid_current
--------------
          633
(1 row)

Session 2
postgres=# begin;
BEGIN
postgres=# select *,xmax from course for share;
 cno |  cname  | credit | priorcourse | xmax
-----+---------+--------+-------------+------
 1   | Chinese |      5 |             |  633
 3   | English |      4 |             |  633
 2   | Physics |      5 |             |  633
(3 rows)

postgres=# select txid_current();
 txid_current
--------------
          634
(1 row)

在compute_new_xmax_infomask函数
Session1的事务已经在xmax字段记录了自己的事务XID,因此会进入TransactionIdIsInProgress(xmax)分支,最终调用MultiXactIdCreate函数创建出一个multi_xact_id = 5。
由于加锁的tuple总共有3个元组,为了避免创建多个multi_xact_id,每个事务会创建一个mcache,当需要创建一个新的multi_xact_id,先遍历mcache中每个组合事务,比对组合事务中的每个成员。如果有完全相同的成员,直接复用已有的multi_xact_id=5。

Session 3
postgres=# select *,xmax from course;
 cno |  cname  | credit | priorcourse | xmax
-----+---------+--------+-------------+------
 1   | Chinese |      5 |             |    5
 3   | English |      4 |             |    5
 2   | Physics |      5 |             |    5

Multixact等待
Session 4
postgres=# begin;
BEGIN
postgres=# select * from course for update;

Session4
Do_MultiXactIdWait
对multixactId成员,循环调用XactLockTableWait,直到所有的加锁事务成员都已经提交或者回滚,才能尝试对元组加update锁。

文章来自个人专栏
Chee
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0