0
点赞
收藏
分享

微信扫一扫

PostgreSQL数据库事务系统——Push\Pop快照


快照使用快照链栈来保存获取的多个快照。栈的元素是ActiveSnapshotElt结构体,ActiveSnapshot指针指向栈顶,OldestActiveSnapshot指向栈底。

/* Elements of the active snapshot stack.
* Each element here accounts for exactly one active_count on SnapshotData.
* NB: the code assumes that elements in this list are in non-increasing
* order of as_level; also, the list must be NULL-terminated. */
typedef struct ActiveSnapshotElt {
Snapshot as_snap;
int as_level;
struct ActiveSnapshotElt *as_next;
} ActiveSnapshotElt;
/* Top of the stack of active snapshots */
static ActiveSnapshotElt *ActiveSnapshot = NULL;
/* Bottom of the stack of active snapshots */
static ActiveSnapshotElt *OldestActiveSnapshot = NULL;

PushActiveSnapshot

PushActiveSnapshot第一步先申请ActiveSnapshotElt内存,第二步判定形参snap是否是CurrentSnapshot或者SecondarySnapshot,或者没有拷贝过,则需要将该快照拷贝到ActiveSnapshotElt的as_snap快照成员,否则直接将snap赋值给ActiveSnapshotElt的as_snap快照成员。

/* PushActiveSnapshot Set the given snapshot as the current active snapshot
* If the passed snapshot is a statically-allocated one, or it is possibly
* subject to a future command counter update, create a new long-lived copy
* with active refcount=1. Otherwise, only increment the refcount. */
void PushActiveSnapshot(Snapshot snap) {
ActiveSnapshotElt *newactive;
Assert(snap != InvalidSnapshot);
newactive = MemoryContextAlloc(TopTransactionContext, sizeof(ActiveSnapshotElt));
/* Checking SecondarySnapshot is probably useless here, but it seems better to be sure. */
if (snap == CurrentSnapshot || snap == SecondarySnapshot || !snap->copied)
newactive->as_snap = CopySnapshot(snap);
else
newactive->as_snap = snap;

newactive->as_next = ActiveSnapshot;
newactive->as_level = GetCurrentTransactionNestLevel();
newactive->as_snap->active_count++;

ActiveSnapshot = newactive;
if (OldestActiveSnapshot == NULL)
OldestActiveSnapshot = ActiveSnapshot;
}

第三步将ActiveSnapshotElt的as_next指向当前栈顶,ActiveSnapshotElt作为当前快照的栈顶,为as_level赋值为GetCurrentTransactionNestLevel(),将快照的active_count自增。(If the passed snapshot is a statically-allocated one, or it is possibly subject to a future command counter update, create a new long-lived copy with active refcount=1. Otherwise, only increment the refcount.)

PostgreSQL数据库事务系统——Push\Pop快照_postgresql

PopActiveSnapshot

从快照链栈中删除栈顶的元素,并减少快照引用计数,如果引用计数为零,需要释放该栈顶快照。

/* PopActiveSnapshot
* Remove the topmost snapshot from the active snapshot stack, decrementing the
* reference count, and free it if this was the last reference. */
void PopActiveSnapshot(void) {
ActiveSnapshotElt *newstack;
newstack = ActiveSnapshot->as_next;
Assert(ActiveSnapshot->as_snap->active_count > 0);
ActiveSnapshot->as_snap->active_count--;
if (ActiveSnapshot->as_snap->active_count == 0 && ActiveSnapshot->as_snap->regd_count == 0)
FreeSnapshot(ActiveSnapshot->as_snap);
pfree(ActiveSnapshot);
ActiveSnapshot = newstack;
if (ActiveSnapshot == NULL) OldestActiveSnapshot = NULL;
SnapshotResetXmin();
}

PostgreSQL数据库事务系统——Push\Pop快照_数据库_02


举报

相关推荐

0 条评论