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

为什么你的单细胞数据总有问题?可能是忽略了scDblFinder这个神器 本文深入剖析了单细胞数据分析中异质性双细胞这一常见但易被忽视的痛点,并重点介绍了scDblFinder这一神器。scDblFinder通过机器学习模型,能精准识别并过滤同一样本内的异质性双细胞,有效解决其导致的聚类模糊、信号混淆等问题,从而显著提升数据洁净度与下游分析结果的可靠性。 阅读详情

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

HeapTupleSatisfiesUpdate函数源码解读

HeapTupleSatisfiesUpdate用于确定一个堆元组在更新操作中是否满足当前事务的可见性及其状态;

函数声明
TM_Result
HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
						 Buffer buffer)

参数说明:

  • HeapTuple htup:指向堆元组指针;
  • CommandId curcid:当前事务的命令ID;
  • Buffer buffer:包含堆元组的缓冲区。w

返回值说明:

  • TM_Ok:元组有效且可见,因此可以被更新;
  • TM_Invisible:当扫描开始时,元组根本不存在;
  • TM_SelfModified:元组在当前事务中被更新,且更新发生在当前扫描开始之后;
  • TM_Updated:元组被已提交的事务更新了(包括元组被移动到不同分区的情况。);
  • TM_Deleted:元组被已提交的事务删除了;
  • TM_BeingModified:元组正在被当前事务之外的进行中的事务更新(包括元组被MultiXact共享锁定的情况,即使MultiXact包括当前事务。)
函数说明:

HeapTupleSatisfiesUpdate函数用于确定一个堆元组在更新操作中是否可见及其状态,并返回TM_Result类型的的值,表示元组的不同状态。该函数的流程图如下:

在这里插入图片描述

函数执行过程
  • 获取元组头,并确保元组的自指针和元组的表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事务已经无效,返回TM_Invisible;
	if (HeapTupleHeaderXminInvalid(tuple))
		return TM_Invisible;
  1. 检查元组是否被标记为HEAP_MOVED_OFF,获取与元组相关的xavc事务ID:
  • 事务IDxvac为当前事务ID,返回TM_Invisible;
  • 事务IDxvac不在进行中且已经提交,则设置Xmin的提示位为HEAP_XMIN_INVALID,返回TM_Invisible;
  • 事务IDxvac不在进行中且没有提交,则设置Xmin的提示位为HEAP_XMIN_COMMITTED。
	/* Used by pre-9.0 binary upgrades */
	if (tuple->t_infomask & HEAP_MOVED_OFF)
	{
		TransactionId xvac = HeapTupleHeaderGetXvac(tuple);

		if (TransactionIdIsCurrentTransactionId(xvac))
			return TM_Invisible;
		if (!TransactionIdIsInProgress(xvac))
		{
			if (TransactionIdDidCommit(xvac))
			{
				SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
							InvalidTransactionId);
				return TM_Invisible;
			}
			SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
						InvalidTransactionId);
		}
	}
  1. 检查元组是否被标记为HEAP_MOVED_IN,获取与元组相关的xavc事务ID:
  • 如果事务IDxvac不是当前事务,且在后台运行中,返回TM_Invisible;
  • 如果事务IDxvac不是当前事务,且已经提交,则设置Xmin的提示位为HEAP_XMIN_COMMITTED;
  • 如果事务IDxvac不是当前事务,且没有提交,则设置Xmin的提示位为HEAP_XMIN_INVALID,返回TM_Invisible。
	else if (tuple->t_infomask & HEAP_MOVED_IN)
	{
		TransactionId xvac = HeapTupleHeaderGetXvac(tuple);

		if (!TransactionIdIsCurrentTransactionId(xvac))
		{
			if (TransactionIdIsInProgress(xvac))
				return TM_Invisible;
			if (TransactionIdDidCommit(xvac))
				SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
							InvalidTransactionId);
			else
			{
				SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
							InvalidTransactionId);
				return TM_Invisible;
			}
		}
	}
  1. 检查Xmin是否时当前事务ID:
	else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
	{
		/* 1. 检查元组的Xmax是否大于当前命令ID */
		/* 2. 检查元组的Xmax是否无效 */
		/* 3. 检查元组是否仅被锁定 */
		/* 4. 检查元组的Xmax是否是组合事务 */
		/* 5. 检查元组的Xmax是否当前事务ID */
		/* 6. 检查元组的cmax是否大于当前命令ID */
	}
  • 如果元组的**cmin(创建命令ID)**大于当前命令ID,返回TM_Invisible,表示元组在扫描后被插入;
	if (HeapTupleHeaderGetCmin(tuple) >= curcid)
		return TM_Invisible;	/* inserted after scan started */
  • 如果元组的Xmax无效,返回TM_OK;
	if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */
		return TM_Ok;
  • 检查元组的Xmax是否仅被锁定,取得Xmax事务ID:
    • 如果元组的Xmax是组合事务且有事务正在进行中,返回TM_BeingModified;
    • 如果元组的Xmax是组合事务但没有事务正在进行,返回TM_Ok;
    • 如果元组的Xmax没有在运行中(已完成)返回TM_Ok;
    • 其他元组的Xmax事务正在进行中,返回TM_BeingModified;
	if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
	{
		TransactionId xmax;

		xmax = HeapTupleHeaderGetRawXmax(tuple);

		/*
		 * Careful here: even though this tuple was created by our own
		 * transaction, it might be locked by other transactions, if
		 * the original version was key-share locked when we updated
		 * it.
		 */

		if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
		{
			if (MultiXactIdIsRunning(xmax, true))
				return TM_BeingModified;
			else
				return TM_Ok;
		}

		/*
		 * If the locker is gone, then there is nothing of interest
		 * left in this Xmax; otherwise, report the tuple as
		 * locked/updated.
		 */
		if (!TransactionIdIsInProgress(xmax))
			return TM_Ok;
		return TM_BeingModified;
	}
  • 如果元组的Xmax的事务是组合事务,取得Xmax事务ID并判断Xmax事务是否有效:
    • 如果Xmax事务不是当前事务ID,且事务在运行中,返回TM_BeingModified;
    • 如果Xmax事务不是当前事务ID,但事务没有运行,返回TM_Ok;
    • 如果Xmax事务是当前事务ID,且cmax(更新命令ID)≥ curcid,返回TM_SelfModified;
    • 如果Xmax事务是当前事务ID,且cmax(更新命令ID)< curcid,返回TM_Invisible;
	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));

		/* deleting subtransaction must have aborted */
		if (!TransactionIdIsCurrentTransactionId(xmax))
		{
			if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple),
										false))
				return TM_BeingModified;
			return TM_Ok;
		}
		else
		{
			if (HeapTupleHeaderGetCmax(tuple) >= curcid)
				return TM_SelfModified; /* updated after scan started */
			else
				return TM_Invisible;	/* updated before scan started */
		}
	}
  • 如果元组的Xmax的事务是当前事务ID,设置标志位为HEAP_XMAX_INVALID,返回TM_Ok;
	if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
	{
		/* deleting subtransaction must have aborted */
		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
					InvalidTransactionId);
		return TM_Ok;
	}
  • 如果元组的Cmax ≥ curcid(当前命令ID),返回TM_SelfModified;
  • 如果元组的Cmax ≥ curcid(当前命令ID),返回TM_Invisible;
	if (HeapTupleHeaderGetCmax(tuple) >= curcid)
		return TM_SelfModified; /* updated after scan started */
	else
		return TM_Invisible;	/* updated before scan started */
  1. 检查Xmin是否在运行,如果在运行返回TM_Invisible;
  2. 检查Xmin是否已提交,如果已提交设置标志位为HEAP_XMIN_COMMITTED;
  3. 否则,Xmin已经中止或者崩溃,设置标志位为HEAP_XMIN_INVALID,返回TM_Invisible;
	else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
		return TM_Invisible;
	else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
		SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
					HeapTupleHeaderGetRawXmin(tuple));
	else
	{
		/* it must have aborted or crashed */
		SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
					InvalidTransactionId);
		return TM_Invisible;
	}
之后,判断Xmax的状态:
  1. 检查Xmax的事务是否无效,如果已经无效,返回TM_Ok;
	if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid or aborted */
		return TM_Ok;
  1. 检查Xmax的事务是否提交,
  • 如果事务已提交且仅被锁定,返回TM_Ok;
  • 如果事务已提交且元组的当前位置和ctid相等,则返回TM_Updated;
  • 如果事务已提交且元组的当前位置和ctid不等,则返回TM_Deleted;
	if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
	{
		if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
			return TM_Ok;
		if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid))
			return TM_Updated;	/* updated by other */
		else
			return TM_Deleted;	/* deleted by other */
	}
  1. 检查Xmax事务是否为组合事务,并获得Xmax事务ID:
	if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
	{
		TransactionId xmax;
		/* 1. 检查Xmax事务是否被锁定更新 */
		/* 2. 检查Xmax事务是否仅被锁定 */
		/* 3. 获取Xmax事务ID并检查其有效性 */
		/* 4. 检查Xmax事务是否是当前事务 */
		/* 5. 检查Xmax事务是否在进行中 */
		/* 6. 检查Xmax事务是否已经提交 */
		/* 7. 检查Xmax事务是否组合事务在运行中 */
	}
  • 如果Xmax被锁定升级,返回TM_OK;
	if (HEAP_LOCKED_UPGRADED(tuple->t_infomask))
		return TM_Ok;
  • 如果Xmax仅被锁定且事务在进行中,返回TM_BeingModified;
  • 如果Xmax仅被锁定且事务不在进行,设置标志位为HEAP_XMAX_INVALID,并返回TM_OK;
	if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
	{
		if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), true))
			return TM_BeingModified;

		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
		return TM_Ok;
	}
  • 获取更新操作的Xmax事务ID,并检查其有效性,如果无效且事务在进行中,返回TM_BeingModified;
	xmax = HeapTupleGetUpdateXid(tuple);
	if (!TransactionIdIsValid(xmax))
	{
		if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
			return TM_BeingModified;
	}
  • 如果Xmax是当前事务ID,且cmax ≥ curcid返回TM_SelfModified;
  • 如果Xmax是当前事务ID,且cmax < curcid返回TM_Invisible;
	/* not LOCKED_ONLY, so it has to have an xmax */
	Assert(TransactionIdIsValid(xmax));

	if (TransactionIdIsCurrentTransactionId(xmax))
	{
		if (HeapTupleHeaderGetCmax(tuple) >= curcid)
			return TM_SelfModified; /* updated after scan started */
		else
			return TM_Invisible;	/* updated before scan started */
	}
  • 如果Xmax事务正在进行中,返回TM_BeingModified;
	if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
		return TM_BeingModified;
  • 如果Xmax事务已提交,比较当前位置的tid和ctid相同,返回TM_Updated;
  • 如果Xmax事务已提交,比较当前位置的tid和ctid不同,返回TM_Deleted;
	if (TransactionIdDidCommit(xmax))
	{
		if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid))
			return TM_Updated;
		else
			return TM_Deleted;
	}
  • 如果Xmax事务不在组合事务中运行,设置标志位为HEAP_XMAX_INVALID,返回TM_Ok;
  • 如果Xmax事务在组合事务中运行,返回TM_BeingModified;
	/*
	 * By here, the update in the Xmax is either aborted or crashed, but
	 * what about the other members?
	 */

	if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
	{
		/*
			* There's no member, even just a locker, alive anymore, so we can
			* mark the Xmax as invalid.
			*/
		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
					InvalidTransactionId);
		return TM_Ok;
	}
	else
	{
		/* There are lockers running */
		return TM_BeingModified;
	}
  1. 检查Xmax事务是否是当前事务ID,如果是当前事务ID:
  • 如果是仅被锁定,返回TM_BeingModified;
  • 如果当前cid ≥ curcid,返回TM_SelfModified,否则返回TM_Invisible;
	if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
	{
		if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
			return TM_BeingModified;
		if (HeapTupleHeaderGetCmax(tuple) >= curcid)
			return TM_SelfModified; /* updated after scan started */
		else
			return TM_Invisible;	/* updated before scan started */
	}
  1. 检查Xmax事务正在进行中,如果正在进行中,返回TM_BeingModified;
	if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
		return TM_BeingModified;
  1. 检查Xmax事务是否提交,如果未提交则设置标志位为HEAP_XMAX_INVALID,并返回TM_Ok;
	if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
	{
		/* it must have aborted or crashed */
		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
					InvalidTransactionId);
		return TM_Ok;
	}
  1. 检查Xmax事务是否仅被锁定,如果锁定则设置标志位为HEAP_XMAX_INVALID,并返回TM_Ok;
	if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
	{
		SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
					InvalidTransactionId);
		return TM_Ok;
	}
  1. 设置Xmax事务标志位为HEAP_XMAX_COMMITTED,并检查当前ctid和ctid,
  • 如果不相等,则返回TM_Updated;
  • 如果相等,则返回TM_Deleted;
	SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
				HeapTupleHeaderGetRawXmax(tuple));
	if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid))
		return TM_Updated;		/* updated by other */
	else
		return TM_Deleted;		/* deleted by other */

该函数通过检查Xmin和Xmax事务的状态(是否已提交、是否进行中、是否是当前事务等),来确定元组对更新是否有效。

AX_COMMITTED,并检查当前ctid和ctid,

  • 如果不相等,则返回TM_Updated;
  • 如果相等,则返回TM_Deleted;
	SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
				HeapTupleHeaderGetRawXmax(tuple));
	if (!ItemPointerEquals(&htup->t_self, &tuple->t_ctid))
		return TM_Updated;		/* updated by other */
	else
		return TM_Deleted;		/* deleted by other */

该函数通过检查Xmin和Xmax事务的状态(是否已提交、是否进行中、是否是当前事务等),来确定元组对更新是否有效。

Unity——Scroll View 滑动居中、居中的放大、其他的缩小(支持横竖Scroll View) 一、效果 二、上代码,两种方式。 (第一种是在Update中用插值完成的,如果不想再项目中看到Update,下面的另一种改了一段用DoTween实现的,需要导入一下DoTween) using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using Unit... 阅读详情

相关推荐

从收音机到Arduino:手把手教你用BJT三极管搭建一个简易音频放大器(附电路图与元件清单)

本文详细介绍了如何使用BJT三极管搭建简易音频放大器,涵盖电路原理、元件选择、设计步骤及调试技巧。通过实践项目帮助电子爱好者深入理解BJT的放大特性,并提供与Arduino结合的扩展应用方案,适合创客和DIY玩家。

aitie1479的博客 437

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

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

米莱虾 262

深入浅出一文搞懂Raft协议

前言 在分布式的世界里,要说最核心最复杂的功能,一致性的实现无出其右,之前的paxos算法堪称经典,被认为是同类算法中效果最好的,基本上成为分布式一致性的代名词,但是paxos算法也是出了名的难理解,而且相当不好实现。本人也花了很多时间、看了很多材料也没有真正理解。所以基于paxos的思想进行的一致性算法的简化和实现就成为了现实的需求,在此背景下,本文的主角Raft就出现了。 Raft算法的头号目标就是容易理解(UnderStandable),这从论文中就可以看出来。当然,R...

microGP的专栏 6485

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

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

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

WangEditor 5.0版本dangerouslyInsertHtml方法的正确使用方式

WangEditor 5.0版本dangerouslyInsertHtml方法的正确使用方式

yang1067155909的专栏 4290

【Office激活】学校正版Office已激活成功仍弹出激活窗口

学校正版Office激活问题:已激活成功仍弹出激活窗口

ESCM_的博客 1万+

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

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

BADAO_LIUMANG_QIZHI的博客 193

【DICOM后处理】qt+vs 实现DICOM数据四视图显示

方法用于 设置 2D 视图的“向上”方向,即定义图像在屏幕坐标系中的朝向。该方法直接影响影像的显示方向,尤其在多平面重建(MPR)或非标准切面显示时至关重要。:方法用于 设置渲染窗口在屏幕上的显示位置(以像素为单位)。它控制的是 VTK 渲染窗口的左上角在屏幕坐标系中的坐标位置。DICOM四视图通常指同时显示医学影像的四个不同平面或视角,用于全面分析三维数据(如CT、MRI等)。:基于 标量值 设置不透明度(控制不同组织的显示),显示骨骼or显示高密度流体等。默认朝向原点 (0, 0, 0)

weixin_41804847的博客 1325

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

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

m0_62221377的博客 425

AgentScope 2.0 API完全指南:构建企业级AI智能体应用的技术实践

本文系统梳理AgentScope 2.0框架的完整API体系,涵盖智能体核心引擎、统一模型适配层、工具系统、消息协议、权限控制与工作空间管理等七大核心模块。通过深入的源码级分析与架构图示,详细解读Agent类的推理-行动循环、ChatModelBase的多模型抽象、Toolkit的工具管理机制、ContentBlock的多模态内容表达、PermissionEngine的安全决策流程,以及Local/Docker/E2B三种工作空间实现。文章还提供了智能客服系统的完整实战案例,展示从自定义工具开发到流式服务部

program哲学 406

ESD防护设计宝典(十):RE(辐射发射)超标问题排查与解决

RE测试是EMC认证的“头号杀手”。当屏幕上出现一根根超标频谱线时,如何快速定位元凶并有效整改?本讲将带你化身电磁侦探,完成一次完美的RE问题“缉凶”。

m0_56451176的博客 394

45-存储过程与函数

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

yuhou25的博客 152

太阳敏感器:卫星姿态控制的“指南针

在卫星姿态控制系统中,太阳敏感器(Sun Sensor) 是至关重要的光学姿态敏感器之一。它通过探测太阳光的方向,为卫星提供关键的姿态参考信息,确保卫星能够正确调整自身方位,维持稳定的对日定向,保障能源供应和任务执行。

ScilogyHunter的博客 1730

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

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

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

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 396

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

数据库主键选型指南:BIGINT vs VARCHAR

主键选型关乎数据库性能与架构演进。BIGINT(如雪花算法)在顺序写入、二级索引开销和分布式生成上优势显著,适合高并发核心链路;而传统 VARCHAR UUIDv4 因随机性导致频繁页分裂、存储膨胀,性能堪忧。UUIDv7 通过时间戳有序性实现高效追加写入,结合 BINARY(16) 存储可兼顾性能与安全,成为现代微服务新选择。关键在于:主键应稳定、无业务含义,优先选用趋势递增的紧凑类型,并根据场景合理采用双主键模式或 ULID 等替代方案。

小李同学的博客 300

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

自动化运维选型:四条技术路线的能力边界,以及它们为什么不能互相替代

自动化运维怎么选型?拆解配置管理、基础设施即代码、作业调度与场景化编排四条技术路线边界,分析账本归属与时间语义差异,给出四种架构组合与判断点,帮企业看清为何不能互相替代。

trainsignalcn的专栏 324

不用再为文本搜索单独维护一套系统!全文检索深度解析

为了给商品、客服工单或者企业知识库增加一个搜索框,企业往往需要在业务数据库之外,再部署一套Elasticsearch。数据库保存商品、订单和用户等真实业务数据,搜索引擎保存另一份文本索引;两套系统之间,还需要通过CDC、消息队列或者同步程序持续传输数据。一个看似简单的搜索需求,最后可能变成两套集群、两份数据和一条必须保持稳定的数据链路。由此产生的问题并不少:数据库已经完成更新,搜索结果却可能尚未同步;业务查询同时涉及文本、库存、权限和订单状态时,应用需要在两个系统之间来回组合结果;

TiDB 社区干货传送门 196

48-逻辑结构表空间段区块

默认 10%,意思是块里的空闲空间低于 10% 时就不再插入新行,留着给已有行的 UPDATE 变胖用。注意 INSERT 过程中每次申请新区,都是一次潜在的空间报错点,如果表空间满了,此刻就会抛 ORA-01653。剩下的空间被谁占了?段的每个区可以落在表空间的任一数据文件,所以 2T 的表在 32G 单文件上限(smallfile)的世界里照样能活——多加文件就行。,一张只有两个 CLOB 字段的表,实际在库里是三个段(表段 + 两个 LOBSEGMENT),空间统计漏算 LOB 段是新手常犯的错。

yuhou25的博客 284

市场调查与统计分析专业大学期间考证怎么安排?

市场调查与统计分析专业的考证规划,适合从一份完整的调查报告倒推:能不能设计问卷、判断样本是否合理、清洗数据,再把分析结果转化为业务建议?围绕这条能力链安排证书,比单纯按“热门程度”报名更有针对性。结合2026年的学习安排,并为2027年的实习、升学和求职预留时间,大学期间可以重点考虑六类证书:全国计算机等级考试证书、大学英语四级或六级成绩报告单、CDA数据分析师、初级统计专业技术资格证书、微软办公软件国际认证中的Excel相关证书,以及软考数据库系统工程师资格证书。

cc572502653的博客 157

QT(了解各个控件及布局)下

练习工程里加一个“确认发送”按钮点击后弹出一个自己写的对话框:一句提示 + “确定”/“取消”确定 → 打印“已确认”,继续发送;取消 → 打印“已取消”,不发送点窗口右上角 X = 取消对话框弹出期间,主窗口点不动(模态)首先我们要在原项目的基础上,新建一个类,就是一个新的小对话框窗口,如下:然后系统会帮我们创建这个新类的头文件和源文件,接着我们到利用ui编辑器设计这个新窗口的界面,如下:如果要实现文字居中,就要设置到QLabel的属性设置这个alignmen为水平中心对齐。

lhbweilai的博客 213

Oracle 19c 在线重定义后旧表空间清理及 ASM 存储资源回收 SOP

Oracle 19c 在线重定义后旧表空间清理与 ASM 存储资源回收 SOP

「YYL DBA手记」 数据库 · 架构 · 运维 · 实战 yyldba.blog.youkuaiyun.com 481
上一篇: 海山数据库(He3DB)源码详解:MVCC可见性HeapTupleSatisfiesToast函数
下一篇: 海山数据库(He3DB)源码详解:海山Mysql 崩溃恢复(1)-准备及结束
DAWN1221
博客等级 码龄7年 893粉丝 95原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值