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

大云海山数据库(He3DB)源码详解:MVCC可见性HeapTupleSatisfiesSelf函数

He3DB_ht 2024-12-14
56

# 海山数据库(He3DB)源码详解:MVCC可见性HeapTupleSatisfiesSelf函数
本文介绍了事务执行过程中,检查一个堆元组是否对当前事务可见,用于确保事务可以看到正确的数据版本。

HeapTupleSatisfiesSelf函数源码解读

HeapTupleSatisfiesSelf:用于判断一个元组是否对当前事务可见;

函数声明

static bool HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)

参数说明:

  • HeapTuple htup:指向堆元组的指针;
  • Snapshot snapshot:元组对应的快照;
  • Buffer buffer:包含堆元组的缓冲区。

函数说明:

该函数用于判断一个元组(tuple)是否对其自身有效,决定了当前事务能否看到某个特定的元组版本。该函数的流程图如下:

在这里插入图片描述

HeapTupleSatisfiesSelf函数过程

  • 获取元组头,并确保元组的自指针和元组的表OID有效
HeapTupleHeader tuple = htup->t_data; Assert(ItemPointerIsValid(&htup->t_self)); Assert(htup->t_tableOid != InvalidOid);
首先,检查Xmin事务是否已经提交,如果没有提交,执行以下过程;
if (!HeapTupleHeaderXminCommitted(tuple)) { /* 1.检查元组的Xmin有效性 */ /* 2.检查元组是否被标记为HEAP_MOVED_OFF */ /* 3.检查元组是否被标记为HEAP_MOVED_IN */ /* 4.检查Xmin事务ID是否为当前事务 */ /* 5.检查Xmin事务ID是否为在运行中 */ /* 6.检查Xmin事务ID是否为已经提交 */ /* 7.其他(事务中止或系统崩溃) */ }
  1. 如果Xmin事务已经提交或者中止,返回false;
if (HeapTupleHeaderXminInvalid(tuple)) return false;
  1. 获取事务IDxvac,并判断是否为当前事务ID,以及是否在进行中:
  • 事务IDxvac为当前事务ID,返回false;
  • 事务IDxvac不在进行中且已经提交,则设置Xmin的提示位为XMIN已无效,返回false;
  • 事务IDxvac不在进行中且没有提交,则设置Xmin的提示位为XMIN已提交(后续执行提交行为)。
/* Used by pre-9.0 binary upgrades */ if (tuple->t_infomask & HEAP_MOVED_OFF) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (TransactionIdIsCurrentTransactionId(xvac)) return false; if (!TransactionIdIsInProgress(xvac)) { if (TransactionIdDidCommit(xvac)) { SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED, InvalidTransactionId); } }
  1. 获取事务IDxvac,并判断是否为当前事务ID:
  • 如果事务IDxvac不是当前事务,且在后台运行中,返回false;
  • 如果事务IDxvac不是当前事务,且已经提交,则设置Xmin的提示位为XMIN已提交;
  • 如果事务IDxvac不是当前事务,且没有提交,则设置Xmin的提示位为XMIN已无效,返回false。
else if (tuple->t_infomask & HEAP_MOVED_IN) { TransactionId xvac = HeapTupleHeaderGetXvac(tuple); if (!TransactionIdIsCurrentTransactionId(xvac)) { if (TransactionIdIsInProgress(xvac)) return false; if (TransactionIdDidCommit(xvac)) SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED, InvalidTransactionId); else { SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; } } }
  1. 依次检查元组Xmax的提示位、锁的状态和事务ID状态:
  • 如果元组的Xmax无效,返回true;
  • 如果元组的Xmax仅是锁定位,返回true;
  • 如果元组的Xmax是组合事务,则获取Xmax的事务ID,并判断是否为当前事务ID,是:返回true,不是:返回false;
  • 如果元组的Xmax的事务ID不是当前事务,设置提示位为XMAX已无效,并返回true;
  • 其他,返回false。
else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple))) { if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */ return true; if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) /* not deleter */ return true; if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { TransactionId xmax; xmax = HeapTupleGetUpdateXid(tuple); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); /* updating subtransaction must have aborted */ if (!TransactionIdIsCurrentTransactionId(xmax)) return true; else return false; } if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple))) { /* deleting subtransaction must have aborted */ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } return false; }
  1. 如果Xmin的事务还在运行中,返回false;
  2. 如果Xmin的事务已经提交,则设置元组提示位为XMIN已提交。
else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple))) return false; else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple))) SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED, HeapTupleHeaderGetRawXmin(tuple));
  1. 其他清空,则设置元组提示位为XMIN已无效,并返回false。
else { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMIN_INVALID, InvalidTransactionId); return false; }
其次,如果Xmin事务已经提交,则判断Xmax的状态:
  1. 如果Xmax无效,返回true;
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */ return true;
  1. 如果Xmax已提交,且有锁定位,返回true;否则返回false;
if (tuple->t_infomask & HEAP_XMAX_COMMITTED) { if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) return true; return false; /* updated by other */ }
  1. 如果Xmax是组合事务,获取Xmax事务的ID,并判断:
  • 如果Xmax仅是锁定位,返回true;
  • 如果是当前事务,返回false;
  • 如果是在运行中,返回true;
  • 如果是已提交,返回false;
  • 其他返回true(中止或者崩溃);
if (tuple->t_infomask & HEAP_XMAX_IS_MULTI) { TransactionId xmax; if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) return true; xmax = HeapTupleGetUpdateXid(tuple); /* not LOCKED_ONLY, so it has to have an xmax */ Assert(TransactionIdIsValid(xmax)); if (TransactionIdIsCurrentTransactionId(xmax)) return false; if (TransactionIdIsInProgress(xmax)) return true; if (TransactionIdDidCommit(xmax)) return false; /* it must have aborted or crashed */ return true; }
  1. 如果Xmax是当前事务,且有锁定位,返回true;无锁定位,返回false;
  2. 如果Xmax的事务在运行中,返回true;
  3. 如果Xmax的事务已提交,设置元组的提示位为XMAX_INVALID,并返回true;
  4. 如果Xmax的事务仅有锁定位,设置元组的提示位为XMAX_INVALID,并返回true;
  5. 其余情况将元组的提示位设置为XMAX_COMMITTED,并返回false。
if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple))) { if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) return true; return false; } if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple))) return true; if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple))) { /* it must have aborted or crashed */ SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } /* xmax transaction committed */ if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask)) { SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId); return true; } SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED, HeapTupleHeaderGetRawXmax(tuple)); return false;

该函数通过检查XminXmax事务的状态(是否已提交、是否进行中、是否是当前事务等),来确定元组对自身是否有效。并且通过设置元组的提示位以有优化未来的可见性检查。

	InvalidTransactionId);
	return true;
}
SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
			HeapTupleHeaderGetRawXmax(tuple));
return false;

该函数通过检查**Xmin**和**Xmax**事务的状态(是否已提交、是否进行中、是否是当前事务等),来确定元组对自身是否有效。并且通过设置元组的提示位以有优化未来的可见性检查。


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

评论