PostgreSQL10基础(7)MVCC

参考书籍: 《PostgreSQL10 High Performance》

MVCC即Multi Version Concurrency Control多版本并发控制,为提升多用户访问同样的数据而设计,性能优于锁定。被广泛用于诸多主流数据库。

内部可见性计算

当一个事务创建时,数据库会更新一个事务ID计算器,通常叫做XID。

  • 当插入一行或更新数据时,一个新行被创建(更新也会创建新行),该新行有一个字段insertion XID(通常称作xmin),记录了当前事务ID
  • 当删除数据时,每个被删除行有个delete XID(通常称作xmax),当行未被删除时值为空
select txid_current(),xmin,xmax,id from test

txid_current()函数返回当前查询的XID

如果一个查询开始,行数据被找到的条件为

(查询XID >= xmin) && ((查询XID <= xmax) || 查询XID is null)

每个数据库客户会话都允许同时修改表,但他们只有在事务提交后才对其他会话可见。

示例

会话1启动事务并更新数据但不提交

# begin;
BEGIN

# select txid_current(),xmin,xmax,* from test;
 txid_current |   xmin   | xmax | id | name
--------------+----------+------+----+------
     81911792 | 81911784 |    0 |  1 | 1
     81911792 | 81911785 |    0 |  2 | 2
(2 rows)

# update test set name='new' where id=2; 
UPDATE 1

dd=# select txid_current(),xmin,xmax,* from test;
 txid_current |   xmin   | xmax | id | name
--------------+----------+------+----+------
     81911792 | 81911784 |    0 |  1 | 1
     81911792 | 81911792 |    0 |  2 | new
(2 rows)

会话2 查询数据

因会话1未提交,会话2XID大于修改数据的XMAX值,因此看不到最新版本数据,只能看到老版本未修改的数据

# select txid_current(),xmin,xmax,* from test;
 txid_current |   xmin   |   xmax   | id | name
--------------+----------+----------+----+------
     81911793 | 81911784 |        0 |  1 | 1
     81911793 | 81911785 | 81911792 |  2 | 2
(2 rows)

会话1 提交

提交后xmax被清空

# commit;
COMMIT

如果会话没有提交而是回滚,则直接删除新版本数据即可。

会话2再次查询(事务中)或新会话 查询数据

因为xmax被清空,因此可以查到提交的数据

# select txid_current(),xmin,xmax,* from test;
 txid_current |   xmin   | xmax | id | name
--------------+----------+------+----+------
     81911794 | 81911784 |    0 |  1 | 1
     81911794 | 81911792 |    0 |  2 | new
(2 rows)

dd=# commit;
COMMIT

更新数据行的实际过程

  • 读入原行数据
  • 根据update修改数据字段
  • 将新数据行及其XID写入到新的磁盘
  • 旧数据行在不再被使用后,可以被Vacuum删除

删除数据行的实际过程

  • 标记原行数据为删除,并更新XID
  • 旧数据行在不再被使用后,可以被Vacuum删除

Heap only tuples(HOT)

上文提到更新和删除的过程,HOT在特定条件下允许直接重用更新和删除操作数据行后的磁盘空间。

例如更新行没有更新任何索引字段,如果新数据行可以被当前数据行所在数据页剩余空间容纳下时。将触发一个数据块上的mini vacuum。正常的Vacuum需要更新数据heap和Index,而mini vacuum只更新数据heap,因此称为heap only。

pg_stat_user_tables视图记录了表上所有更新次数n_tup_upd和HOT更新次数n_tup_hot_upd

MVCC优缺点

优点

最大程度避免了锁定,读数据不会与写数据发生冲突,读不会阻塞写,写也不会阻塞读。

缺点

  • 占用了磁盘空间,需要进行Vacuum清扫
    • 更新时使用了新的磁盘,老数据未被删除
    • 删除时老数据未被真正删除磁盘
  • 要当心不可重复读和脏读问题

事务ID环绕

事务ID是32比特,大约20亿个ID,超出则会变为0。MVVC的可见机制将会出现问题。

为了解决问题

  • 每个数据库和每张表都有一个引用XID,可见于pg_class表relfrozenxid字段,该字段记录本表或数据库最小XID,小于该值得XID都见被置为保留的冻结ID,Vacuum将处理这些XID
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章