Skip to content

Latest commit

 

History

History
184 lines (151 loc) · 7.52 KB

20231130_02.md

File metadata and controls

184 lines (151 loc) · 7.52 KB

PostgreSQL 17 preview - Add tests for XID wraparound

作者

digoal

日期

2023-11-30

标签

PostgreSQL , PolarDB , duckdb , xid , wraparound


背景

《Use pg_resetxlog simulate tuple disappear within PostgreSQL》

使用pg_resetxlog可以模拟xid的耗尽, 从而模拟tuple不可见的情况.

现在PostgreSQL 17直接提供了一个测试插件, 用于模拟快速消耗xid.

CREATE EXTENSION xid_wraparound;

两个接口函数如下:
consume_xids(nxids bigint)
consume_xids_until(targetxid xid8)  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=e255b646a16b45823c338dadf787813fc9e191dc

Add tests for XID wraparound. master github/master  
  
author	Masahiko Sawada <msawada@postgresql.org>	  
Thu, 30 Nov 2023 05:29:48 +0000 (14:29 +0900)  
committer	Masahiko Sawada <msawada@postgresql.org>	  
Thu, 30 Nov 2023 05:29:48 +0000 (14:29 +0900)  
commit	e255b646a16b45823c338dadf787813fc9e191dc  
tree	7fd87cf5d0e8caf51d8ba886904757e0569b8469	tree  
parent	a243569bf65c5664436e8f63d870b7ee9c014dcb	commit | diff  
Add tests for XID wraparound.  
  
The test module includes helper functions to quickly burn through lots  
of XIDs. They are used in the tests, and are also handy for manually  
testing XID wraparound.  
  
Since these tests are very expensive the entire suite is disabled by  
default. It requires to set PG_TEST_EXTRA to run it.  
  
Reviewed-by: Daniel Gustafsson, John Naylor, Michael Paquier  
Reviewed-by: vignesh C  
Author: Heikki Linnakangas, Masahiko Sawada, Andres Freund  
Discussion: https://www.postgresql.org/message-id/CAD21AoDVhkXp8HjpFO-gp3TgL6tCKcZQNxn04m01VAtcSi-5sA%40mail.gmail.com  
   1 /* src/test/modules/xid_wraparound/xid_wraparound--1.0.sql */  
   2   
   3 -- complain if script is sourced in psql, rather than via CREATE EXTENSION  
   4 \echo Use "CREATE EXTENSION xid_wraparound" to load this file. \quit  
   5   
   6 CREATE FUNCTION consume_xids(nxids bigint)  
   7 RETURNS xid8 IMMUTABLE PARALLEL SAFE STRICT  
   8 AS 'MODULE_PATHNAME' LANGUAGE C;  
   9   
  10 CREATE FUNCTION consume_xids_until(targetxid xid8)  
  11 RETURNS xid8 IMMUTABLE PARALLEL SAFE STRICT  
  12 AS 'MODULE_PATHNAME' LANGUAGE C;  
/*  
  68  * Common functionality between the two public functions.  
  69  */  
  70 static FullTransactionId  
  71 consume_xids_common(FullTransactionId untilxid, uint64 nxids)  
  72 {  
  73     FullTransactionId lastxid;  
  74     uint64      last_reported_at = 0;  
  75     uint64      consumed = 0;  
  76   
  77     /* Print a NOTICE every REPORT_INTERVAL xids */  
  78 #define REPORT_INTERVAL (10 * 1000000)  
  79   
  80     /* initialize 'lastxid' with the system's current next XID */  
  81     lastxid = ReadNextFullTransactionId();  
  82   
  83     /*  
  84      * We consume XIDs by calling GetNewTransactionId(true), which marks the  
  85      * consumed XIDs as subtransactions of the current top-level transaction.  
  86      * For that to work, this transaction must have a top-level XID.  
  87      *  
  88      * GetNewTransactionId registers them in the subxid cache in PGPROC, until  
  89      * the cache overflows, but beyond that, we don't keep track of the  
  90      * consumed XIDs.  
  91      */  
  92     (void) GetTopTransactionId();  
  93   
  94     for (;;)  
  95     {  
  96         uint64      xids_left;  
  97   
  98         CHECK_FOR_INTERRUPTS();  
  99   
 100         /* How many XIDs do we have left to consume? */  
 101         if (nxids > 0)  
 102         {  
 103             if (consumed >= nxids)  
 104                 break;  
 105             xids_left = nxids - consumed;  
 106         }  
 107         else  
 108         {  
 109             if (FullTransactionIdFollowsOrEquals(lastxid, untilxid))  
 110                 break;  
 111             xids_left = U64FromFullTransactionId(untilxid) - U64FromFullTransactionId(lastxid);  
 112         }  
 113   
 114         /*  
 115          * If we still have plenty of XIDs to consume, try to take a shortcut  
 116          * and bump up the nextXid counter directly.  
 117          */  
 118         if (xids_left > 2000 &&  
 119             consumed - last_reported_at < REPORT_INTERVAL &&  
 120             MyProc->subxidStatus.overflowed)  
 121         {  
 122             int64       consumed_by_shortcut = consume_xids_shortcut();  
 123   
 124             if (consumed_by_shortcut > 0)  
 125             {  
 126                 consumed += consumed_by_shortcut;  
 127                 continue;  
 128             }  
 129         }  
 130   
 131         /* Slow path: Call GetNewTransactionId to allocate a new XID. */  
 132         lastxid = GetNewTransactionId(true);  
 133         consumed++;  
 134   
 135         /* Report progress */  
 136         if (consumed - last_reported_at >= REPORT_INTERVAL)  
 137         {  
 138             if (nxids > 0)  
 139                 elog(NOTICE, "consumed %llu / %llu XIDs, latest %u:%u",  
 140                      (unsigned long long) consumed, (unsigned long long) nxids,  
 141                      EpochFromFullTransactionId(lastxid),  
 142                      XidFromFullTransactionId(lastxid));  
 143             else  
 144                 elog(NOTICE, "consumed up to %u:%u / %u:%u",  
 145                      EpochFromFullTransactionId(lastxid),  
 146                      XidFromFullTransactionId(lastxid),  
 147                      EpochFromFullTransactionId(untilxid),  
 148                      XidFromFullTransactionId(untilxid));  
 149             last_reported_at = consumed;  
 150         }  
 151     }  
 152   
 153     return lastxid;  
 154 }  

digoal's wechat