海山数据库(He3DB)源码详解:两阶段提交(2PC)事务块内核函数执行过程

解密微信视频号推荐算法的三大核心机制 本文深入解析微信视频号推荐算法的三大核心机制:用户行为数据、视频内容质量和社交关系链。通过详细的数据分析和实战测试,揭示算法如何根据完播率、互动深度、原创性检测和社交关系等因素决定内容推荐。帮助用户和创作者更好地理解并利用视频号算法,提升内容曝光和观看体验。 阅读详情

海山数据库(He3DB)源码详解:两阶段提交(2PC)事务块内核函数执行过程

本文介绍了两阶段提交(2PC)事务执行过程中,主要讲解事务的prepare阶段和commit阶段的内核函数执行过程。

前言

两阶段提交(2PC)是一种用于分布式系统的事务处理协议,旨在确保事务的原子性。以下是2PC从事务准备到提交或放弃的执行流程图:

graph TD
    A[开始] --> B[事务发起者请求所有参与者准备]
    B --> C{所有参与者是否准备好?}
    C -- 是 --> D[事务发起者发送提交请求]
    C -- 否 --> E[事务发起者发送放弃请求]
    D --> F{所有参与者是否同意提交?}
    F -- 是 --> G[所有参与者提交事务]
    F -- 否 --> H[所有参与者放弃事务]
    E --> I[所有参与者放弃事务]
    G --> J[事务提交完成]
    H --> J
    I --> J
    J --> K[结束]

流程说明:

  1. 开始:事务发起者(协调者)开始一个新的分布式事务。
  2. 事务发起者请求所有参与者准备:协调者向所有参与者发送准备请求,询问它们是否准备好提交事务。
  3. 所有参与者是否准备好?:这是一个决策点,需要等待所有参与者的响应。
    • 是:如果所有参与者都准备好了,协调者将发送提交请求。
    • 否:如果任何一个参与者没有准备好,协调者将发送放弃请求。
  4. 事务发起者发送提交请求:协调者向所有参与者发送提交事务的请求。
  5. 所有参与者是否同意提交?:这是另一个决策点,需要等待所有参与者的响应。
    • 是:如果所有参与者都同意提交,它们将执行提交操作。
    • 否:如果任何一个参与者拒绝提交,所有参与者将放弃事务。
  6. 所有参与者提交事务:参与者执行实际的提交操作,使事务永久生效。
  7. 所有参与者放弃事务:参与者执行回滚操作,撤销所有事务相关的更改。
  8. 事务提交完成:事务要么成功提交,要么被放弃,分布式事务到此结束。
  9. 结束:2PC过程完成。

处理TRANS_STMT_PREPARE

当终端输入PREPARE TRANSACTION xxx语句时,这时一个会发起2PC的事务提交准备过程。处理过程首先会调用PrepareTransactionBlock()函数,并根据返回值判断是否时错误结束发生回滚。

PrepareTransactionBlock()函数执行过程:

  1. 首先,该函数会调用EndTransactionBlock()函数,获得一个事务结束的返回值;
    TransactionState s;
	bool		result;

	/* Set up to commit the current transaction */
	result = EndTransactionBlock(false);
  1. 然后,判断result的值,如果为true,修改其他block的状态;如果为false,表示事务出错,准备进行回滚;
	if (result)
	{
		s = CurrentTransactionState;

		while (s->parent != NULL)
			s = s->parent;

		if (s->blockState == TBLOCK_END)
		{
			/* Save GID where PrepareTransaction can find it again */
			prepareGID = MemoryContextStrdup(TopTransactionContext, gid);

			s->blockState = TBLOCK_PREPARE;
		}
		else
		{
			/*
			 * ignore case where we are not in a transaction;
			 * EndTransactionBlock already issued a warning.
			 */
			Assert(s->blockState == TBLOCK_STARTED ||
				   s->blockState == TBLOCK_IMPLICIT_INPROGRESS);
			/* Don't send back a PREPARE result tag... */
			result = false;
		}
	}
  • 首先,获得当前事务的状态结构体,并找到事务的根节点;
  • 之后,判断节点的状态是否为END,如果是,则将当前的gid深拷贝一份,交给全局静态变量prepareGID,并修改事务块的状态为TBLOCK_PREPARE;否则,将返回结构result改为false,准备进行回滚。

根据PrepareTransactionBlock()返回值对事务进行标记

如果PrepareTransactionBlock()函数的返回值为false,则会将事务标记为CMDTAG_ROLLBACK,这意味着当前的事务将被中止,并且事务所作的所有更新都会被丢弃,回到事务开始之前的状态。调用SetQueryCompletion()函数对传入参数qc进行修改,完成事务的标记。

处理TRANS_STMT_COMMIT_PREPARED

当终端输入COMMIT PREPARED xxx语句时,这时会发起一个2PC的事务提交过程。处理过程首先会调用PreventInTransactionBlock()函数,检查当前分布式事务和事务块的状态。然后调用FinishPreparedTransaction()函数,执行分布式事务提交操作。

PreventInTransactionBlock()函数执行过程

  1. 调用IsTransactionBlock()检查全局结构体变量CurrentTransactionState中的blockState成员值,如果blockState等于TBLOCK_DEFAULT或者TBLOCK_STARTED,表示不存在事务块,返回false,其他返回true:
	if (IsTransactionBlock())
		ereport(ERROR,
				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
		/* translator: %s represents an SQL statement name */
				 errmsg("%s cannot run inside a transaction block",
						stmtType)));
  1. 调用IsSubTransaction()检查全局结构体变量CurrentTransactionState中的nestingLevel成员值,如果≥2表示有子事务嵌套,返回true,否则返回false:
    if (IsSubTransaction())
		ereport(ERROR,
				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
		/* translator: %s represents an SQL statement name */
				 errmsg("%s cannot run inside a subtransaction",
						stmtType)));
  1. 检查全局int变量MyXactFlag的值,如果等于XACT_FLAGS_PIPELINING,表示事务处于管道模式。
	if (MyXactFlags & XACT_FLAGS_PIPELINING)
		ereport(ERROR,
				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
		/* translator: %s represents an SQL statement name */
				 errmsg("%s cannot be executed within a pipeline",
						stmtType)));
  • 补充: 管道模式和2PC(两阶段提交)之间的冲突主要体现在以下几个方面:
  1. 检查是否为TopLevel:
	if (!isTopLevel)
		ereport(ERROR,
				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
		/* translator: %s represents an SQL statement name */
				 errmsg("%s cannot be executed from a function", stmtType)));
  1. 检查当前事务块状态:
	if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
		CurrentTransactionState->blockState != TBLOCK_STARTED)
		elog(FATAL, "cannot prevent transaction chain");
  1. 将全局int变量MyXactFlag的与XACT_FLAGS_NEEDIMMEDIATECOMMIT做位或操作
    MyXactFlags |= XACT_FLAGS_NEEDIMMEDIATECOMMIT;

FinishPreparedTransaction()函数执行过程

  1. 首先,申请执行过程所需要的所有变量:
	GlobalTransaction gxact;
	PGPROC	   *proc;
	TransactionId xid;
	char	   *buf;
	char	   *bufptr;
	TwoPhaseFileHeader *hdr;
	TransactionId latestXid;
	TransactionId *children;
	RelFileNode *commitrels;
	RelFileNode *abortrels;
	RelFileNode *delrels;
	int			ndelrels;
	xl_xact_stats_item *commitstats;
	xl_xact_stats_item *abortstats;
	SharedInvalidationMessage *invalmsgs;
  • GlobalTransaction gxact;

    • 这是一个结构体,用于表示全局事务数据的类型,主要跟踪prepared transactions(即那些已经被准备好但尚未提交的事务)。
  • PGPROC *proc;

    • PGPROC 是 PostgreSQL 中的一个结构体,代表一个后端进程。这个指针用于指向当前事务的后端进程结构。
  • TransactionId xid;

    • TransactionId 是 PostgreSQL 中用于唯一标识一个事务的类型。这个变量存储了当前事务的 ID。
  • char *buf;

    • 这是一个字符指针,用于存储事务日志记录的缓冲区。
  • char *bufptr;

    • 这是另一个字符指针,用作 buf 的游标或指针,用于在缓冲区中移动和处理数据。
  • TwoPhaseFileHeader *hdr;

    • TwoPhaseFileHeader 是一个结构体,用于存储两阶段提交协议的文件头信息。这个指针可能指向一个这样的结构体实例,包含有关两阶段提交的元数据。
  • TransactionId latestXid;

    • 这个变量存储了最新的事务 ID,用于跟踪事务日志中的最新事务。
  • TransactionId *children;

    • 这是一个指向 TransactionId 的指针数组,用于存储当前事务的子事务 ID。
  • RelFileNode *commitrels;

    • 这是一个指向 RelFileNode 的指针数组,用于存储需要在事务提交时处理的关联关系文件节点。
  • RelFileNode *abortrels;

    • 类似于 commitrels,这个指针数组用于存储需要在事务中止时处理的关联关系文件节点。
  • RelFileNode *delrels;

    • 这个指针数组用于存储需要删除的关联关系文件节点。
  • int ndelrels;

    • 这个整数变量表示 delrels 数组中的元素数量。
  • xl_xact_stats_item *commitstats;

    • 这是一个指针,指向存储提交事务统计信息的结构体。
  • xl_xact_stats_item *abortstats;

    • 类似于 commitstats,这个指针指向存储中止事务统计信息的结构体。
  • SharedInvalidationMessage *invalmsgs;

    • 这是一个指针,指向共享无效消息,用于在事务处理过程中通知其他节点或进程某些数据已失效。
  1. 验证GID并锁定GXACT,获取对应GXACT的后端proc,获取GXACT的xid。
	/*
	 * Validate the GID, and lock the GXACT to ensure that two backends do not
	 * try to commit the same GID at once.
	 */
	gxact = LockGXact(gid, GetUserId());
	proc = &ProcGlobal->allProcs[gxact->pgprocno];
	xid = gxact->xid;
  • 验证GID: GID 通常指的是全局事务标识符(Global Transaction Identifier)。验证 GID 意味着检查这个标识符是否有效,是否存在于系统中,以及是否对应于一个已经准备好但尚未提交的事务。这是为了确保你正在处理的是一个有效的、待提交的事务。

  • 锁定GXACT: GXACT 可能是指全局事务数据结构(Global Transaction Actor)。锁定 GXACT 是为了防止多个后端(backend)进程或线程同时尝试提交同一个 GID 对应的事务。这种锁定机制是必要的,因为在一个分布式系统中,可能同时有多个节点或进程参与事务的处理。

  • 保两个后端不会尝试一次提交相同的 GID: 这句话的意思是确保不会有两次提交操作同时对同一个 GID 进行。在分布式系统中,不同的后端可能指的是不同的数据库节点、不同的事务管理器或不同的服务实例。它们可能都参与了同一个全局事务的处理,但是由于网络分区、节点故障恢复或其他原因,可能会出现多个节点尝试提交同一个事务的情况。为了防止数据不一致或其他问题,需要确保对于任何一个给定的 GID,在同一时间内只有一个后端可以进行提交操作。

  1. 检查gxact->ondisk,如果成立就从磁盘上读取2PC状态数据,如果不成立就从Xlog日志中读取2PC状态数据。
	if (gxact->ondisk)
		buf = ReadTwoPhaseFile(xid, false);
	else
		XlogReadTwoPhaseData(gxact->prepare_start_lsn, &buf, NULL);
  1. 从buf中读取数据并初始化申请的变量。
	hdr = (TwoPhaseFileHeader *) buf;
	Assert(TransactionIdEquals(hdr->xid, xid));
	bufptr = buf + MAXALIGN(sizeof(TwoPhaseFileHeader));
	bufptr += MAXALIGN(hdr->gidlen);
	children = (TransactionId *) bufptr;
	bufptr += MAXALIGN(hdr->nsubxacts * sizeof(TransactionId));
	commitrels = (RelFileNode *) bufptr;
	bufptr += MAXALIGN(hdr->ncommitrels * sizeof(RelFileNode));
	abortrels = (RelFileNode *) bufptr;
	bufptr += MAXALIGN(hdr->nabortrels * sizeof(RelFileNode));
	commitstats = (xl_xact_stats_item *) bufptr;
	bufptr += MAXALIGN(hdr->ncommitstats * sizeof(xl_xact_stats_item));
	abortstats = (xl_xact_stats_item *) bufptr;
	bufptr += MAXALIGN(hdr->nabortstats * sizeof(xl_xact_stats_item));
	invalmsgs = (SharedInvalidationMessage *) bufptr;
	bufptr += MAXALIGN(hdr->ninvalmsgs * sizeof(SharedInvalidationMessage));
  1. 获取主xact及其子项中的最新XID,并关闭中断。
    latestXid = TransactionIdLatest(xid, hdr->nsubxacts, children);
    HOLD_INTERRUPTS();
  1. 判断isCommit值,根据判断结果选择执行提交(commit)还是放弃(abort)。
	if (isCommit)
		RecordTransactionCommitPrepared(xid,
										hdr->nsubxacts, children,
										hdr->ncommitrels, commitrels,
										hdr->ncommitstats,
										commitstats,
										hdr->ninvalmsgs, invalmsgs,
										hdr->initfileinval, gid);
	else
		RecordTransactionAbortPrepared(xid,
									   hdr->nsubxacts, children,
									   hdr->nabortrels, abortrels,
									   hdr->nabortstats,
									   abortstats,
									   gid);
    ProcArrayRemove(proc, latestXid);
    gxact->valid = false;
  • 当isCommit为true时,会调用RecordTransactionCommitPrepared函数记录事务提交日志;
  • 当isCommit为false时,会调用RecordTransactionAbortPrepared函数记录事务放弃日志;
  • 从全局 ProcArray 中移除 PGPROC,移除 PGPROC 条目意味着该事务不再被视为活跃,TransactionIdIsInProgress函数将不再报告该事务正在进行中;
  • 将全局事务的valid成员值改为false,表示该事务不在后端进程中。
  1. 判断isCommit值,根据判断结果对变量delrels和ndelrels进行赋值,然后进行对应Relation文件的的删除,以及执行计划内的删除。
	if (isCommit)
	{
		delrels = commitrels;
		ndelrels = hdr->ncommitrels;
	}
	else
	{
		delrels = abortrels;
        ndelrels = hdr->nabortrels;
    }
    DropRelationFiles(delrels, ndelrels, false);
    
	if (isCommit)
		pgstat_execute_transactional_drops(hdr->ncommitstats, commitstats, false);
	else
		pgstat_execute_transactional_drops(hdr->nabortstats, abortstats, false);
  • 当isCommit为true时,调用commitrels和hdr的ncommitrels成员两个值对变量进行赋值,表示进行提交的节点删除;
  • 当isCommit为false时,调用abortrels和hdr的nabortrels成员两个值对变量进行赋值,表示进行放弃的节点删除;
  • DropRelationFiles函数会调用smgrdounlinkall函数,作用是将给定的所有SMgrRelation对象的所有分支(forks)从磁盘中移除,确保数据库系统中不再需要的文件被彻底清除,以释放存储空间,并保持文件系统的整洁。执行 smgrdounlinkall 函数的具体步骤通常包括:
    1. 从共享缓冲池中移除所有相关的数据页。
    2. 关闭所有 SMgrRelation 对象的所有分支。
    3. 注册 SMgrRelation 对象与物理文件的无效映射信息,并告知其他进程。
    4. 删除所有 SMgrRelation 对象的所有分支所对应的物理文件。
  • 根据isCommit的值,调用pgstat_execute_transactional_drops函数执行计划内的删除,主要是一些被标记为删除的对象(如表、索引、视图等)能够从实际统计信息中移除,具体来说,pgstat_execute_transactional_drops会执行以下操作:
    • 在事务提交时,它会删除那些在事务中被删除的对象的统计信息。
    • 在事务回滚时,它会撤销对统计信息的任何修改,因为事务中的更改没有实际发生。
    • 这个函数确保了统计信息的一致性,避免了因为事务中的删除操作而导致的统计信息不一致的问题。
  1. 当事务提交时,确保所有相关的缓存和共享数据结构都被正确地更新或失效,以反映事务中所做的更改。
	if (isCommit)
	{
		if (hdr->initfileinval)
			RelationCacheInitFilePreInvalidate();
		SendSharedInvalidMessages(invalmsgs, hdr->ninvalmsgs);
		if (hdr->initfileinval)
			RelationCacheInitFilePostInvalidate();
	}

  • 检查是否需要初始化文件失效(initfileinval):

    • hdr->initfileinval 检查是否需要进行初始化文件失效的操作。如果为真,表示需要在事务提交前处理相关的缓存失效。
  • 执行初始化文件预失效(PreInvalidate)操作:

    • RelationCacheInitFilePreInvalidate() 函数被调用,以处理在发送共享失效消息(Shared Invalid Messages)之前需要进行的缓存失效操作。这通常涉及到关系缓存(relation cache)的初始化文件,确保在事务提交过程中,相关的缓存信息是最新的。
  • 发送共享失效消息:

    • SendSharedInvalidMessages(invalmsgs, hdr->ninvalmsgs) 函数被调用,发送共享失效消息。这些消息通知其他数据库进程,某些数据或结构已经改变,需要更新它们的缓存。invalmsgs 是一个包含失效消息的数组,hdr->ninvalmsgs 是这个数组中的元素数量。
  • 执行初始化文件后失效(PostInvalidate)操作:

    • 如果 hdr->initfileinval 为真,RelationCacheInitFilePostInvalidate() 函数被调用,以处理在发送共享失效消息之后需要进行的缓存失效操作。这确保了在事务提交后,相关的缓存信息也是最新的。

共享失效消息(Shared Invalidation Messages)是 PostgreSQL 中用于维护缓存一致性的一种机制。当数据库中的某些数据被修改时,这些修改可能会影响到其他数据库进程中的缓存数据。为了确保所有进程中的缓存数据保持一致,PostgreSQL 通过共享失效消息来通知其他进程,某些缓存数据已经不再有效,需要被刷新或更新。

这些失效消息通过一个共享内存中的队列(shmInvalBuffer)来传递,这个队列被所有数据库进程共享。当一个事务提交时,它会发送这些失效消息到其他后端进程,以便它们可以更新自己的缓存。这种机制确保了在高并发环境下,不同事务对同一数据的修改不会导致缓存不一致的问题。

  1. 加锁处理事务提交或者放弃阶段的回调函数过程,释放事务所持有的谓词锁以及清理全局事务的共享内存。
	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);

	/* And now do the callbacks */
	if (isCommit)
		ProcessRecords(bufptr, xid, twophase_postcommit_callbacks);
	else
		ProcessRecords(bufptr, xid, twophase_postabort_callbacks);

	PredicateLockTwoPhaseFinish(xid, isCommit);

	/* Clear shared memory state */
	RemoveGXact(gxact);

	/*
	 * Release the lock as all callbacks are called and shared memory cleanup
	 * is done.
	 */
	LWLockRelease(TwoPhaseStateLock);
  • ProcessRecords 回调函数的作用是处理事务日志中记录的各种操作。这些操作可能包括数据的修改、锁的获取和释放、存储管理器(storage manager)的操作等。ProcessRecords 回调函数会被调用来遍历事务日志中的每一条记录,并执行相应的操作来提交或回滚事务。
    具体来说,ProcessRecords 回调函数可能执行以下类型的操作:
    1. 数据修改:将事务中对数据的修改应用到数据库中,或者在回滚时撤销这些修改。
    2. 锁处理:在事务提交时释放锁,或者在回滚时保持锁的状态。
    3. 存储管理器操作:处理与物理存储相关的操作,如文件的创建、删除等。
    4. 系统目录更新:更新系统目录信息,以反映事务对数据库结构的更改。
  • PredicateLockTwoPhaseFinish处理和释放一个准备好的事务在提交或中止时持有的谓词锁,无论是成功提交还是由于某种原因中止,都需要确保之前设置的谓词锁被释放,以避免死锁和其他事务的不一致性问题。
  • RemoveGXact会处理共享内存中的全局事务,注意:这里的全局事务必须以及从Proc Array中移除了。
  1. 更新和清理事务的统计信息,处理2PC文件,将该进程的全局事务指针置空,开放终端,释放内存,结束函数。
	/* Count the prepared xact as committed or aborted */
	AtEOXact_PgStat(isCommit, false);

	/* And now we can clean up any files we may have left. */
	if (gxact->ondisk)
		RemoveTwoPhaseFile(xid, true);

	MyLockedGxact = NULL;

	RESUME_INTERRUPTS();

	pfree(buf);
  • AtEOXact_PgStat主要负责更新统计信息,这些统计信息包括但不限于表和索引的访问统计、函数调用统计等,具体来说会执行以下操作:
    • 更新表和索引的统计信息,如访问次数、行数变化等。
    • 更新函数调用的统计信息,如调用次数和执行时间。
    • 清理事务中产生的临时统计信息。
    • 确保统计信息的准确性和及时性,以便查询优化器可以使用这些信息来优化查询计划。
      与pgstat_execute_transactional_drops函数的区别:
    • AtEOXact_PgStat 函数更关注于更新和清理事务中的统计信息;
    • pgstat_execute_transactional_drops 函数则专注于处理事务中对象的创建和删除对统计信息的影响。
  • 调用RemoveTwoPhaseFile函数处理2PC文件。每个事务在进行两阶段提交时,会创建一个临时文件来记录事务的状态,直到事务最终提交或中止。这个文件被称为两阶段提交文件(2PC 文件),它包含了完成两阶段提交协议所需的信息。
  • 当前由本进程锁定的全局事务条目指针MyLockedGxact置为空;
  • 放开中断,并释放buf对应的内存空间。

处理TRANS_STMT_ROLLBACK_PREPARED

当终端输入ABORT PREPARED xxx语句时,这时会发起一个2PC的事务放弃过程。整体流程和2PC的提交过程类似,所以这里不做过多的讲解。

FPGA上的YOLOv8加速实现:从Verilog到高层综合 YOLOv8 采用了更高效的C2f模块与轻量化Backbone结构,模型特征包括:结构紧凑、检测头融合高低层特征;支持Anchor-free检测机制;支持INT8、FP16低精度推理;计算密度高,适合FPGA并行优化。 阅读详情

相关推荐

FPGA防抄板实战:如何利用Xilinx芯片的“身份证”(DNA)实现你的加密锁?

本文深入探讨了如何利用Xilinx FPGA芯片的DNA(Device Native Authentication)功能实现硬件级加密保护,防止设计被抄袭。文章详细解析了DNA的物理实现、获取方式,并提供了从DNA到加密密钥的转换方法,以及构建商业级加密防护系统的实战方案。通过JTAG和原语两种读取方式的对比,帮助开发者选择最适合的方案。

weixin_42548829的博客 383

海山数据库(He3DB)源码解读:2PC

两阶段提交(2PC)是一种用于分布式系统的事务处理协议,旨在确保事务的原子性。以下是2PC从事务准备到提交或放弃的执行流程图:开始:事务发起者(协调者)开始一个新的分布式事务。事务发起者请求所有参与者准备:协调者向所有参与者发送准备请求,询问它们是否准备好提交事务。所有参与者是否准备好?:这是一个决策点,需要等待所有参与者的响应。是:如果所有参与者都准备好了,协调者将发送提交请求。否:如果任何一个参与者没有准备好,协调者将发送放弃请求。事务发起者发送提交请求。

weixin_51457815的博客 981

单相PWM整流器四象限运行原理

简述单相PWM整流器四象限运行原理。

m0_75208156的博客 8298

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 195

YOLOv13改进策略【特征提取层】| 引入注意力卷积模块RFAConv,关注感受野空间特征 助力yolov13精度提升

RFAConv:创新空间注意力和标准卷积运算感受野空间特征是针对卷积核设计的,根据卷积核大小动态生成。以3×3卷积核为例,它由非重叠滑动窗口组成,每个窗口代表一个感受野滑块。

Limiiiing的博客 359

YOLO11涨点优化:知识蒸馏 | 引入FGD(Focal and Global Distillation)蒸馏,让轻量学生模型汲取大模型全局感知力

文章摘要 目标检测模型YOLO11在轻量化部署中存在"全局盲区"问题,即轻量模型感受野不足导致大尺度场景下性能下降。知识蒸馏技术FGD(Focal and Global Distillation)通过双分支机制有效解决这一问题:Focal Distillation分离前景背景特征,让学生模型聚焦关键区域;Global Distillation传递像素间关系信息,弥补全局感知缺陷。实验表明,FGD可使YOLO11轻量版mAP提升2.5%以上,且不增加推理耗时。本文详细解析了FGD原理,并给出YOLO11上的实

2601_95807009的博客 226

在Codex 让AI模型 拥有长期智能记忆

本文介绍Claude-Mem V15新功能——智能记忆召回,解决AI遗忘、重复提示、执行不一致等问题。通过本地部署claude-mem,实现自动记录决策(如数据库选型)、跨会话智能召回,支持记忆写入、检索、遗忘全流程闭环。相比传统记忆方案,其基于Hooks自动捕获工具调用,结构化存储,可追溯、可共享、可清理,显著提升工程效率与协作一致性,是长期项目中理想的“工作黑匣子”与“工程脑”。

米莱虾 265

出现 Tomcat:HTTP状态 404 - 未找到解决方法(图文分析)

出现如下问题 HTTP状态 404 - 未找到 类型 状态报告 消息 请求的资源[/ajax_war_exploded/]不可用 描述 源服务器未能找到目标资源的表示或者是不愿公开一个已经存在的资源表示。 Apache Tomcat/8.5.69 解决方法如下: 网上中的操作有步操作多数都误导 这个部署的环境目录上面是web.xml 下面的目录路径是web即可不用到webapp 保存重启服务器即可使用 其他配置中启动tomcat的操作具体 JRE 1.8 ...

码农研究僧的博客 13万+

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 117

AI测试干货:Claude Code Skill 从入门到精通

本文介绍了Claude Code Skill功能如何解决AI重复工作问题。传统提示词方式需要人工复制粘贴,而Skill功能通过建立AI工作记忆库实现智能触发和分层加载。Skill包含工作指令、文档和资源,能自动执行任务。文章以API测试用例生成为例,展示了Skill的创建流程和结构化设计,包括测试框架、覆盖场景和输出格式,显著提升测试工程师的工作效率。

blues_C的博客 2438

100天精通Python(爬虫篇)——第118天:selenium自动化操作浏览器基础大总结

一、Selenium框架环境搭建 1. 下载模块 2. 安装浏览器驱动WebDriver 二、基础操作 1. 打开浏览器 2. 无界面模式 3. 元素定位 4. 元素操作 5. 前进后退 6. 执行js 7.页面等待 隐式等待(常用) 显式等待(了解) 三、进阶操作 1. 使用代理ip 2. 修改请求头 3. 隐藏指纹特征.....................

努力让自己发光,对的人才能迎着光而来 10万+

Docker Compose:搭建本地多服务开发环境

从一个 Java API、PostgreSQL 和 Redis 开始,配置服务名、端口、环境变量、健康检查、数据卷和依赖关系。理解 Compose 文件如何被解析、项目如何隔离,以及哪些数据不能依赖“重建容器”保留,能够把个人开发环境整理成团队可复用的启动入口。

m0_62221377的博客 428

在群辉(NAS)中安装虚拟机套件(Virtual Machine Manager)

一、在群辉中下载虚拟机套件Virtual Machine Manager ①启用Open vSwitch(网络-->管理--启用Open vSwitch) ②打开“套件中心” ③查找到Virtual Machine Manager套件点击“安装套件” 二、安装虚拟机套件(Virtual Machine Manager) ①打开虚拟机套件运行设置向导 ②选择存储空间...

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 2万+

45-存储过程与函数

匿名块跑完就没了,想下次再用只能复制粘贴。给块起个名字存进数据库,就成了存储过程与函数:一次编译、处处调用、权限收口,还能让 Java 侧少拼 SQL。这篇讲封装、调用、限制与排错的完整套路。CREATE OR REPLACE 覆盖式创建,事务由调用方控制;参数三模式 IN 只进、OUT 只出、IN OUT 双向,OUT 参数调用时要备好变量接;调用三姿势 EXEC、CALL、匿名块,命名传参=>最清晰;函数必有 RETURN,想在 SQL 里调用就不能碰 DML 和事务控制;

yuhou25的博客 152

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

AI全栈实战 | 3.9-01 爬虫入门:requests 加 BeautifulSoup 三分钟跑通,但 90% 的人栽在这 4 个“礼貌“问题上

⚠️:本文内容仅用于。请遵守目标站点的服务条款与相关法律法规,不得对目标服务造成负担,不得采集、传播个人隐私数据。技术是中性的,边界在你手里。爬虫的入门技术(requests 发请求 + BeautifulSoup 解析)三分钟就能学会。真正区分"会用爬虫"和"会做爬虫的人"的,是这篇我们跑通"请求→解析→存储"的最小闭环,然后重点把"合规与礼貌"这根弦给你绷上。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 393

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

上一篇: 海山数据库(He3DB)源码解读:T_GrantRoleStmt原理浅析
下一篇: 海山数据库(He3DB)源码详解:事务块执行过程及内核函数
DAWN1221
博客等级 码龄7年 893粉丝 95原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值