事务ID使用 unsigned int(0~4294967295)类型进行存储,当事务号耗尽则重新循环使用,从3开始
typedef uint32 TransactionId;
保留0、1、2作为特殊事务号,其中2为冻结事务号比所有事务号老,即对所有事务可见
#define InvalidTransactionId ((TransactionId) 0)
#define BootstrapTransactionId ((TransactionId) 1)
#define FrozenTransactionId ((TransactionId) 2)
#define FirstNormalTransactionId ((Trujuku ansactionId) 3)
#define MaxTransactionId ((TransactionId) 0xFFFFFFFF)
数据库函数age(xid)获取年龄的c实现,即当前xid减去参数xid
Datum
xid_age(PG_FUNCTION_ARGS)
{
TransactionId xid = PG_GETARG_TRANSACTIONID(0);
TransactionId now = GetStableLatestTransactionId();
/* Permanent XIDs are always infinitely old */
if (!TransactionIdIsNormal(xid))
PG_RETURN_INT32(INT_MAX);
PG_RETURN_INT32((int32) (now - xid));
}
xidWrapLimit = oldest_datfrozenxid + (MaxTransactionId >> 1);
xidStopLimit = xidWrapLimit - 1000000;
xidWarnLimit = xidStopLimit - 10000000;
xidVacLimit = oldest_datfrozenxid + autovacuum_freeze_max_age;
autovacuum:自动vaccum/analyze开关
autovacuum_freeze_max_age:强制执行autovacuum的数据库年龄,即年龄大于此参数必须进行vaccum(无论autovacuum是否打开)
autovacuum_vacuum_scale_factor:update/delete记录数占表记录数的百分比
autovacuum_vacuum_threshold:最小update/delete记录数
vacuum_freeze_min_age:最小需要进行表记录冻结的年龄,最大值为autovacuum_freeze_max_age的一半
vacuum_freeze_table_age:需进行全表扫描进行冻结的年龄,最大值为autovacuum_freeze_max_age*0.95
autovacuum打开:(update/delete的记录数>=autovacuum_vacuum_scale_factor*表记录总数+autovacuum_vacuum_threshold)or (表的年龄>=autovacuum_freeze_max_age)
vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples;
*dovacuum = force_vacuum || (vactuples > vacthresh);
autovacuum关闭:(表的年龄>=autovacuum_freeze_max_age)and (当前事务号 % 65536 == 0 )
if (TransactionIdFollowsOrEquals(xid, ShmemVariableCache->xidVacLimit))
{
............................
if (IsUnderPostmaster && (xid % 65536) == 0)
SendPostmasterSignal(PMSIGNAL_START_AUTOVAC_LAUNCHER);
....................................
partscan/惰性模式:基于可见性映射表扫描非all_visible的数据页进行垃圾回收或事务冻结,每32个连续数据页判断一次是否可以跳过,存在一个不能跳过的页则全不跳过
/*
* Before we consider skipping a page that's marked as clean in
* visibility map, we must've seen at least this many clean pages.
*/
#define SKIP_PAGES_THRESHOLD ((BlockNumber) 32)
fullscan/积极模式:基于可见性映射表扫描全表进行垃圾回收或事务冻结,但跳过all_frozen的数据页
aggressive = TransactionIdPrecedesOrEquals(onerel->rd_rel->relfrozenxid,xidFullScanLimit);
if (options & VACOPT_DISABLE_PAGE_SKIPPING)
aggressive = true;
小于freezeLimit标识的事务号均为可冻结的
oldestXmin:根据长事务中最老XID、slot_xmin、slot_catalog_xmi、vacuum_defer_cleanup_age、old_snapshot_threshold等计算得出数据库需要保留的最小XID,即不能进行冻结处理的事务号。
freezeLimit:vaccum能进行冻结处理的最大XID,当(oldestXmin-vacuum_freeze_min_age)<(当前XID - autovacuum_freeze_max_age)时,值为(oldestXmin),反之则为(oldestXmin-vacuum_freeze_min_age)
小结
if (vacstmt->options & VACOPT_FREEZE)
{
params.freeze_min_age = 0;
params.freeze_table_age = 0;
}
如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!
赞1
添加新评论0 条评论