海山数据库(He3DB)源码解读:BEGIN-END-ABORT

C-Lodop打印服务系统存在任意文件读取 阅读详情

# 海山数据库(He3DB)源码详解:事务块执行过程及内核函数

本文介绍了事务执行过程中,从BEGIN事务开始到事务结束END/ABORT的内核函数执行过程。

前言:

事务SQL语句的执行过程,会先通过事务块函数修改事务块状态,然后根据事务块状态执行不同的事务行为。因此,本章会讲解事务块的开始和结束过程的事务块函数。

事务块控制事务执行的过程:

在讲具体函数之前,有必要在此讲解一下,事务块是如何控制事务行为的。事务管理器中,事务块会根据当前事务状态,来控制具体的事务操作行为,具体流程如下:

在这里插入图片描述

  • 开始事务块:表示一个新的事务块的开始。
  • 检查事务状态:检查当前事务的状态,是否活跃、空闲或处于错误状态。
    • 活跃:如果事务处于活跃状态,执行事务操作。
      • 执行事务操作:执行具体的事务操作,如插入、更新或删除数据。
    • 空闲:如果事务处于空闲状态,等待操作命令。
      • 等待操作命令:在事务空闲时等待接收到新的操作命令。
      • 接收到操作命令:一旦接收到操作命令,开始执行事务操作。
    • 执行事务操作:执行具体的事务操作,如插入、更新或删除数据。
      • 操作成功?:检查事务操作是否成功。
      • 提交事务:如果操作成功,提交事务。
      • 回滚事务:如果操作失败或事务处于错误状态,回滚事务。
    • 错误:如果事务处于错误状态,进行回滚操作。
      • 回滚事务:如果操作失败或事务处于错误状态,回滚事务。
  • 结束事务块:表示事务块的结束,此时事务已经提交或回滚。

如何进行事务块操作:

使用 BEGIN 命令可以手动控制启动事务的边界,开始一个新的事务块;
使用 END \COMMIT 命令可以手动控制结束事务,结束一个执行中的事务块;
使用 ABORT \ ROLLBACK 命令可以手动控制放弃回滚事务,结束一个出错的事务块;
当执行这些SQL语句时,系统底层会调用相对应的事务块函数,来修改当前事务块的状态,从而控制具体的事务操作行为。其中,事务块操作的开始和结束分别对应的函数为:

  1. BEGIN 对应的事务块函数为 BeginTransactionBlock() 函数;
  2. END \ COMMIT 对应的事务块函数为 EndTransactionBlock() 函数;
  3. ABORT \ ROLLBACK 对应的事务块函数为 UserAbortTransactionBlock() 函数。
    那么,这些函数的执行流程是什么样的?

BeginTransactionBlock()函数的执行过程:

当终端输入BEGIN或者START TRANSACTION命令时,会开始一个事务块。处理过程首先会调用BeginTransactionBlock()函数。该函数内部主体为一个switch结构,会对枚举类型TBlockState中的所有状态都进行一个判断,并作一个对应的处理。执行过程示意图如下:

在这里插入图片描述

  1. 首先通过全局变量CurrentTransactionState获得当前事务块状态的变量;

     TransactionState s = CurrentTransactionState;
    
  2. 然后通过switch-case结构,根据当前事务块状态做对应的操作,其中有包括:

  • 如果当前事务块状态为TBLOCK_STARTED,则修改为TBLOCK_BEGIN;
        case TBLOCK_STARTED:
    		s->blockState = TBLOCK_BEGIN;
    		break;
    
  • 如果当前事务块状态为TBLOCK_IMPLICIT_INPROGRESS,则修改为TBLOCK_BEGIN;
        case TBLOCK_IMPLICIT_INPROGRESS:
    		s->blockState = TBLOCK_BEGIN;
    		break;
    
  • 如果当前事务块状态为TBLOCK_INPROGRESS、TBLOCK_PARALLEL_INPROGRESS、TBLOCK_SUBINPROGRESS、TBLOCK_ABORT和TBLOCK_SUBABORT,会进行WARNING报警,但是不会影响执行过程,可以继续执行;
        case TBLOCK_INPROGRESS:
    	case TBLOCK_PARALLEL_INPROGRESS:
    	case TBLOCK_SUBINPROGRESS:
    	case TBLOCK_ABORT:
    	case TBLOCK_SUBABORT:
    		ereport(WARNING,
    				(errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    				 errmsg("there is already a transaction in progress")));
    		break;
    
  • 如果当前事务块状态为上述提到的其他状态,则直接报FATAL错误,直接退出事务块过程;
        case TBLOCK_DEFAULT:
    	case TBLOCK_BEGIN:
    	case TBLOCK_SUBBEGIN:
    	case TBLOCK_END:
    	case TBLOCK_SUBRELEASE:
    	case TBLOCK_SUBCOMMIT:
    	case TBLOCK_ABORT_END:
    	case TBLOCK_SUBABORT_END:
    	case TBLOCK_ABORT_PENDING:
    	case TBLOCK_SUBABORT_PENDING:
    	case TBLOCK_SUBRESTART:
    	case TBLOCK_SUBABORT_RESTART:
    	case TBLOCK_PREPARE:
    		elog(FATAL, "BeginTransactionBlock: unexpected state %s",
    			 BlockStateAsString(s->blockState));
    		break;
    

以上,就是BeginTransactionBlock()函数的全部执行过程。

EndTransactionBlock()函数的执行过程:

当终端输入COMMIT或者EDN语句时,这时一个事务块会发起提交或者结束,如果输入END,正确结束为提交,错误结束为回滚。处理过程首先会调用EndTransactionBlock()函数,并根据返回值判断是否时错误结束发生回滚。EndTransactionBlock()函数和BeginTransactionBlock()十分相似,内部主要是一个swith结构,这里直接说执行流程:

在这里插入图片描述

  1. 首先通过全局变量CurrentTransactionState获得当前事务块状态的变量,并定义返回值bool变量result;

     TransactionState s = CurrentTransactionState;
     bool		result = false;
    
  2. 然后通过switch-case结构,根据当前事务块状态做对应的操作,其中有包括:

  • 如果当前事务块状态为TBLOCK_INPROGRESS,则修改为TBLOCK_END,并将变量result赋值为true;
     case TBLOCK_INPROGRESS:
         s->blockState = TBLOCK_END;
         result = true;
         break;
    
  • 如果当前事务块状态为TBLOCK_IMPLICIT_INPROGRESS,表示当前处在一个隐式的事务进程模式。判断入参chain的值,如果为true,表示该状态下存在子事务,报Error错误,退出事务执行过程;否则报Warning,修改事务块状态为TBLOCK_END,并将变量result赋值为true;
     case TBLOCK_IMPLICIT_INPROGRESS:
         if (chain)
             ereport(ERROR,
                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
             /* translator: %s represents an SQL statement name */
                         errmsg("%s can only be used in transaction blocks",
                             "COMMIT AND CHAIN")));
         else
             ereport(WARNING,
                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
                         errmsg("there is no transaction in progress")));
         s->blockState = TBLOCK_END;
         result = true;
         break;
    
  • 如果当前事务块状态为TBLOCK_ABORT,只修改事务块状态为TBLOCK_ABORT_END;
     case TBLOCK_ABORT:
         s->blockState = TBLOCK_ABORT_END;
         break;
    
  • 如果当前事务块状态为TBLOCK_SUBINPROGRESS,表示当前事务属于正常状态可以提交,需要从当前节点逐级回溯到父节点,并修改过程中每个节点的状态;
     case TBLOCK_SUBINPROGRESS:
         while (s->parent != NULL)
         {
             if (s->blockState == TBLOCK_SUBINPROGRESS)
                 s->blockState = TBLOCK_SUBCOMMIT;
             else
                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
                         BlockStateAsString(s->blockState));
             s = s->parent;
         }
         if (s->blockState == TBLOCK_INPROGRESS)
             s->blockState = TBLOCK_END;
         else
             elog(FATAL, "EndTransactionBlock: unexpected state %s",
                     BlockStateAsString(s->blockState));
         result = true;
         break;
    
    • 首先,通过while循环,回溯每个节点,并对每个节点的事务块状态进行判断。如果是TBLOCK_SUBINPROGRESS,则修改为TBLOCK_SUBCOMMIT,由后续的CommitSubTransaction()函数中进行提交,如果是其他,则直接报FATAL错误,退出事务操作过程;
    • 退出while后,判断父节点事务块状态,如果是TBLOCK_INPROGRESS,则修改为TBLOCK_END,表示事务完成,后续由CommitTransaction()函数完成具体的事务提交,如果是其他,报FATAL错误;
    • 最后修改返回值result为true。
  • 如果当前事务块状态为TBLOCK_SUBABORT,表示当前事务整体处于放弃状态,需要从当前节点逐级回溯到父节点,并修改过程中每个节点的状态以实现整体事务的放弃;
     case TBLOCK_SUBABORT:
         while (s->parent != NULL)
         {
             if (s->blockState == TBLOCK_SUBINPROGRESS)
                 s->blockState = TBLOCK_SUBABORT_PENDING;
             else if (s->blockState == TBLOCK_SUBABORT)
                 s->blockState = TBLOCK_SUBABORT_END;
             else
                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
                         BlockStateAsString(s->blockState));
             s = s->parent;
         }
         if (s->blockState == TBLOCK_INPROGRESS)
             s->blockState = TBLOCK_ABORT_PENDING;
         else if (s->blockState == TBLOCK_ABORT)
             s->blockState = TBLOCK_ABORT_END;
         else
             elog(FATAL, "EndTransactionBlock: unexpected state %s",
                     BlockStateAsString(s->blockState));
         break;
    
    • 首先,通过while循环,回溯每个节点,并对每个节点的事务块状态进行判断。如果是TBLOCK_SUBINPROGRESS,则修改为TBLOCK_SUBABORT_PENDING,表示处于准备放弃的状态,后续会通过AbortSubTransaction()和CleanupSubTransaction()函数处理;如果是TBLOCK_SUBABORT,则修改为TBLOCK_SUBABORT_END,表示处于结束放弃的状态,已经由AbortSubTransaction()函数处理过,后续只需要通过CleanupSubTransaction()清理相关资源即可;如果是其他,则直接报FATAL错误,退出事务操作过程;
    • 退出while后,判断父节点事务块状态,如果是TBLOCK_INPROGRESS,则修改为TBLOCK_ABORT_PENDING,表示事务准备放弃,后续由AbortTransaction()和CleanupTransaction()函数处理;如果是TBLOCK_ABORT,则修改为TBLOCK_ABORT_END,表示处于结束放弃的状态,已经由AbortTransaction()函数处理过,后续只需要通过CleanupTransaction()清理相关资源即可;如果是其他,报FATAL错误。
  • 如果当前事务块状态为TBLOCK_STARTED,表示当前事务执行出错,需要通过chain判断错误的严重性。判断入参chain的值,如果为true,表示当前状态下存在子事务,报Error错误,退出事务执行过程;否则报Warning,并将变量result赋值为true;
     if (chain)
         ereport(ERROR,
                 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
         /* translator: %s represents an SQL statement name */
                     errmsg("%s can only be used in transaction blocks",
                         "COMMIT AND CHAIN")));
     else
         ereport(WARNING,
                 (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
                     errmsg("there is no transaction in progress")));
     result = true;
     break;
    
  • 如果当前事务块状态为TBLOCK_PARALLEL_INPROGRESS,表示当前事务处于并行操作的状态,不能有parallel worker进行提交,报FATAL错误,直接退出事务操作过程;
     case TBLOCK_PARALLEL_INPROGRESS:
         ereport(FATAL,
                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
                     errmsg("cannot commit during a parallel operation")));
         break;
    
  • 如果处于其他状态,则表示当前事务状态出现预料之外的情况,报FATAL错误,直接退出事务操作过程。
         /* These cases are invalid. */
     case TBLOCK_DEFAULT:
     case TBLOCK_BEGIN:
     case TBLOCK_SUBBEGIN:
     case TBLOCK_END:
     case TBLOCK_SUBRELEASE:
     case TBLOCK_SUBCOMMIT:
     case TBLOCK_ABORT_END:
     case TBLOCK_SUBABORT_END:
     case TBLOCK_ABORT_PENDING:
     case TBLOCK_SUBABORT_PENDING:
     case TBLOCK_SUBRESTART:
     case TBLOCK_SUBABORT_RESTART:
     case TBLOCK_PREPARE:
         elog(FATAL, "EndTransactionBlock: unexpected state %s",
                 BlockStateAsString(s->blockState));
         break;
    

UserAbortTransactionBlock()函数执行过程:

当终端输入ROLLBACK语句时,这时会发起一个事务的回滚操作,放弃之前的所有操作,数据库回滚到事务开始之前的样子。通过调用UserAbortTransactionBlock()函数执行该过程。该函数和其他事务块操作函数十分相似,内部主要是一个swith结构,这里直接说执行流程:
在这里插入图片描述

  1. 首先通过全局变量CurrentTransactionState获得当前事务块状态的变量;
    TransactionState s = CurrentTransactionState;
  1. 然后通过switch-case结构,根据当前事务块状态做对应的操作,其中有包括:
  • 如果事务块处在TBLOCK_INPROGRESS状态下,将状态修改为TBLOCK_ABORT_PENDING;
	case TBLOCK_INPROGRESS:
        s->blockState = TBLOCK_ABORT_PENDING;
        break;   
  • 如果事务块处在TBLOCK_ABORT状态下,将状态修改为TBLOCK_ABORT_END;
	case TBLOCK_ABORT:
        s->blockState = TBLOCK_ABORT_END;
        break;  
  • 如果事务块处在TBLOCK_SUBINPROGRESS或TBLOCK_SUBABORT,标记每个子事务状态为放弃状态,直到top事务位置;
    case TBLOCK_SUBINPROGRESS:
    case TBLOCK_SUBABORT:
        while (s->parent != NULL)
        {
            if (s->blockState == TBLOCK_SUBINPROGRESS)
                s->blockState = TBLOCK_SUBABORT_PENDING;
            else if (s->blockState == TBLOCK_SUBABORT)
                s->blockState = TBLOCK_SUBABORT_END;
            else
                elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
                        BlockStateAsString(s->blockState));
            s = s->parent;
        }
        if (s->blockState == TBLOCK_INPROGRESS)
            s->blockState = TBLOCK_ABORT_PENDING;
        else if (s->blockState == TBLOCK_ABORT)
            s->blockState = TBLOCK_ABORT_END;
        else
            elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
                    BlockStateAsString(s->blockState));
        break;  
  • 循环检查当前节点的父节点状态,如果不为空,则根据blockState值对应修改当前事务的事务块状态,并将事务指针指向父节点;

  • 当循环到top节点时,退出循环,并根据top节点的blockState值对应修改当前top事务的事务块状态。

  • 如果事务块处在TBLOCK_STARTED或TBLOCK_IMPLICIT_INPROGRESS,根据chain的值报ERROR或者WARING错误,并将事务块状态修改为TBLOCK_ABORT_PENDING;

    case TBLOCK_STARTED:
    case TBLOCK_IMPLICIT_INPROGRESS:
        if (chain)
            ereport(ERROR,
                    (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
            /* translator: %s represents an SQL statement name */
                        errmsg("%s can only be used in transaction blocks",
                            "ROLLBACK AND CHAIN")));
        else
            ereport(WARNING,
                    (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
                        errmsg("there is no transaction in progress")));
        s->blockState = TBLOCK_ABORT_PENDING;
        break;

  • 如果chain为true,表示事务的链式执行,事务在结束后会开启一个新事务,如果开启则汇报ERROR错误;

  • 如果chain为false,报WARIING错误,修改事务块状态。

  • 如果务块处在TBLOCK_PARALLEL_INPROGRESS,则直接报FATAL错误。

    case TBLOCK_PARALLEL_INPROGRESS:
        ereport(FATAL,
                (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
                    errmsg("cannot abort during a parallel operation")));
        break;

原因:事务管理系统设计上避免在并行执行的事务中执行 ABORT,以维护系统的稳定性和数据的一致性。这种设计确保了并行查询的性能和可靠性。

  • 如果事务块处于其他状态,直接FATAL。
    case other_TBLOCK:
        elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
                BlockStateAsString(s->blockState));
        break;
  • 对当前事务块状态做判断,并保存chain的值到
	Assert(s->blockState == TBLOCK_ABORT_END ||
		   s->blockState == TBLOCK_ABORT_PENDING);

	s->chain = chain;
统设计上避免在并行执行的事务中执行 ABORT,以维护系统的稳定性和数据的一致性。这种设计确保了并行查询的性能和可靠性。

- 如果事务块处于其他状态,直接FATAL。
```C 
    case other_TBLOCK:
        elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
                BlockStateAsString(s->blockState));
        break;
  • 对当前事务块状态做判断,并保存chain的值到
	Assert(s->blockState == TBLOCK_ABORT_END ||
		   s->blockState == TBLOCK_ABORT_PENDING);

	s->chain = chain;
在 SAP S/4HANA Public Cloud 中做产品扩展:从 Key User 到 ABAP Cloud 与 BTP 的三轨实践指南 摘要:SAP S/4HANA Public Cloud 提供三种扩展方式(key user、developer extensibility 和 side-by-side),遵循 clean core 原则确保升级稳定。key user 扩展适合无代码轻量改良,developer extensibility 用于受控 ABAP 开发,side-by-side 则适用于云原生独立应用。文章通过销售订单优先级字段、退货审批微服务和采购校验等案例,说明不同扩展路径的适用场景与实现方法,帮助开发者在三系统景观中合理选 阅读详情

相关推荐

告别IMEI!手把手教你用UUID实现Android设备唯一标识(兼容Android 10-13)

本文详细探讨了在Android 10及以上版本中,如何构建合规且高可用的设备唯一标识方案以替代被限制访问的IMEI。文章深入分析了Android设备标识符的演变,并提供了基于UUID/GUID的完整实现策略,包括生成算法、多级持久化存储方案(如MediaStore)、权限处理以及版本兼容性实践,帮助开发者应对Android 10-13的隐私政策变化。

weixin_28339967的博客 573

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

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

BADAO_LIUMANG_QIZHI的博客 195

实战:如何通过修改VTS和HTS调整GC4653 sensor帧率(附完整计算步骤)

本文以GC4653图像传感器为例,详细解析了通过修改VTS和HTS寄存器来精确调整输出帧率的完整流程。文章深入剖析了帧率计算公式FPS = PCLK / (VTS × HTS)的核心原理,并提供了从获取寄存器参数、计算目标VTS值到系统验证的实战步骤,帮助工程师掌握独立优化Sensor性能、提升低照度画质的关键技能。

gin88的博客 338

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

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

米莱虾 265

从零构建:如何用MATLAB打造你的第一个Stewart平台运动学仿真器

本文详细介绍了如何使用MATLAB从零构建一个六自由度Stewart平台运动学仿真器,涵盖基础理论、环境配置、运动学建模、动态轨迹规划和实时可视化实现。通过MATLAB的Robotics System Toolbox和Simulink等工具,读者可以掌握六自由度Stewart平台的逆运动学求解、正运动学求解及仿真系统集成,适用于飞行模拟器和精密定位等应用场景。

peach的博客 864

【脑电绘图教程 2】使用Brainstorm进行脑电处理及源定位

Brainstorm 是一个开源应用程序,支持MEG、EEG、fNIRS、ECoG、深度电极和其他电生理学的数据分析,尤其用于MEG、EEG的源定位。Brainstorm的主要优点是其简单直观的图形界面,不需要进行任何编程,即可上手MEG、EEG分析,此外,它还支持多种数据类型(基本上EEGLab支持的,它都支持),并且具有数据批量处理功能,可以很方便的分析自己的数据。

qq_40735196的博客 1万+

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

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

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

大语言模型无代码构建知识图谱概述

由示例可以看出,大语言模型的泛化能力能够非常精准的抽取文本中的实体、关系等知识信息。其能够大大提升知识提取的效率与准确性。HuggingFists低代码平台的出现进一步促进了知识图谱构建的效率。它大幅降低了知识图谱构建人员的技术要求,使得从事该工作的人员有了更大的选择范围。不断下降的构建成本,意味着可以有更多的客户享受到知识图谱带来的业务价值。

colorknight的专栏 1817

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

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

m0_62221377的博客 427

aic8800出现insmod: can‘t insert ‘/lib/modules/4.9.191/aic8800_fdrv.ko‘: No such device

2、如果单独编译wifi驱动,则把CONFIG_PLATFORM_UBUNTU?= y都改为CONFIG_PLATFORM_ALLWINNER?1、如果把wifi驱动嵌入到内核编译,则在makefile中加入这一句。后面再修改对应平台的交叉编译链和内核吗路径等。

mantouyouyou的博客 510

匹配博弈双边选择算法

刚学图论匹配方面的一些知识,记录下来。

ymengm的博客 2434

45-存储过程与函数

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

yuhou25的博客 152

Google Earth Engine 实现图像随机森林分类_遥感分类全流程详解

本文将通过一段完整的GEE代码,逐步讲解如何利用Sentinel-2影像和随机森林算法,实现地表覆盖分类。代码包含等关键步骤,适合遥感入门学习!

国科大硕士在读,分享Python/GEE/Matlab/R专业代码实践,涵盖数据分析、算法开发与应用技巧等,以代码会友。 916

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

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

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

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

数据库乐观锁深度解析: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的专栏 397

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

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

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

小李同学的博客 300

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

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

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

trainsignalcn的专栏 324

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

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

TiDB 社区干货传送门 205

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

AI Agent记忆从不是向量库:Oracle拆解读写分离与记忆晋升门,终结无脑存聊天的伪智能——读Wojtek Pluta演讲

在过去一年里,绝大多数团队在为自己的 AI Agent 增加“记忆能力”时,做法几乎如出一辙:开一个向量数据库(Pinecone / Milvus / Chroma),在每轮对话结束时,把用户的提问和 Agent 的回复转成 Embedding 向量直接往里塞;<summary> 审查 Kyle 的贷款完整性,审批未通过,等待补件。这种记忆能力完全脱离了脆弱的会话上下文窗口,靠的是数据库底座驱动的显式记忆装配。在写路径中,决定一条信息能否从“临时上下文”跃升为“长期持久化记忆”的核心关卡,正是。

鲜衣怒马楼兰月 129
上一篇: 海山数据库(He3DB)源码解读:2PC
下一篇: 海山数据库(He3DB)源码解读:SubBegin-Rollback
DAWN1221
博客等级 码龄7年 893粉丝 95原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值