当前位置: 首页 > news >正文

Postgresql源码(123)事务提交时三段资源释放分析ResourceOwnerRelease

0 总结

  1. 三段释放原因:因为如果先释放锁,没有释放一些共享资源(比如pin住的buffer),别人拿到锁后发现我们仍然持有一些资源,就会有问题。所以三阶段释放主要是以锁为分界线,先释放锁保护的资源,在释放锁,在清理私有资源。这样可以保证别人拿到锁后,一定也能拿到对应的资源。
  2. 三段:先放pinned buffer、relation、dsm这些共享资源;再放锁;所有放其他会话看不到的私有资源。

1 资源随事务释放

三阶段释放是指ResourceOwnerRelease函数在使用时需要调用三次,按固定顺序调用每次删除特定的资源:

  1. RESOURCE_RELEASE_BEFORE_LOCKS
  2. RESOURCE_RELEASE_LOCKS
  3. RESOURCE_RELEASE_AFTER_LOCKS
typedef enum
{RESOURCE_RELEASE_BEFORE_LOCKS = 1,RESOURCE_RELEASE_LOCKS,RESOURCE_RELEASE_AFTER_LOCKS,
} ResourceReleasePhase;

例如事务提交时CommitTransaction:

static void
CommitTransaction(void).........ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_BEFORE_LOCKS,true, true);/* Check we've released all buffer pins */AtEOXact_Buffers(true);/* Clean up the relation cache */AtEOXact_RelationCache(true);/** Make catalog changes visible to all backends.  This has to happen after* relcache references are dropped (see comments for* AtEOXact_RelationCache), but before locks are released (if anyone is* waiting for lock on a relation we've modified, we want them to know* about the catalog change before they start using the relation).*/AtEOXact_Inval(true);AtEOXact_MultiXact();ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_LOCKS,true, true);ResourceOwnerRelease(TopTransactionResourceOwner,RESOURCE_RELEASE_AFTER_LOCKS,true, true);......

其他几个事务控制函数资源释放时,也是按照相同的顺序分三阶段释放的:

函数名phaseisCommitisTopLevel
CommitTransactionRESOURCE_RELEASE_BEFORE_LOCKStruetrue
CommitTransactionRESOURCE_RELEASE_LOCKStruetrue
CommitTransactionRESOURCE_RELEASE_AFTER_LOCKStruetrue
PrepareTransactionRESOURCE_RELEASE_BEFORE_LOCKStruetrue
PrepareTransactionRESOURCE_RELEASE_LOCKStruetrue
PrepareTransactionRESOURCE_RELEASE_AFTER_LOCKStruetrue
AbortTransactionRESOURCE_RELEASE_BEFORE_LOCKSfalsetrue
AbortTransactionRESOURCE_RELEASE_LOCKSfalsetrue
AbortTransactionRESOURCE_RELEASE_AFTER_LOCKSfalsetrue
CommitSubTransactionRESOURCE_RELEASE_BEFORE_LOCKStruefalse
CommitSubTransactionRESOURCE_RELEASE_LOCKStruefalse
CommitSubTransactionRESOURCE_RELEASE_AFTER_LOCKStruefalse
AbortSubTransactionRESOURCE_RELEASE_BEFORE_LOCKSfalsefalse
AbortSubTransactionRESOURCE_RELEASE_LOCKSfalsefalse
AbortSubTransactionRESOURCE_RELEASE_AFTER_LOCKSfalsefalse

2 为什么要分三阶段释放?

结论

因为如果先释放锁,没有释放一些共享资源(比如pin住的buffer),别人拿到锁后发现我们仍然持有一些资源,就会有问题。所以三阶段释放主要是以锁为分界线,先释放锁保护的资源,在释放锁,在清理私有资源。这样可以保证别人拿到锁后,一定也能拿到对应的资源。

  1. RESOURCE_RELEASE_BEFORE_LOCKS(预锁定阶段):需要释放对其他后端可见的资源(pinned buffers)。为了确保当我们释放另一个后端可能正在等待的锁时,它会看到我们已经完全退出了我们的事务。这是为了防止在释放锁之后,其他后端仍然看到我们持有的资源,从而可能导致数据不一致或其他问题。
  2. RESOURCE_RELEASE_LOCKS(锁定阶段):释放持有的所有锁。这是为了让其他可能正在等待这些锁的后端能够继续执行。
  3. RESOURCE_RELEASE_AFTER_LOCKS(后锁定阶段):后端内部的清理工作。释放那些只有后端自己知道的、不会影响其他后端的资源。

3 代码分析

下面这次提交后对resowner做了扩展性增强,代码逻辑没变但可读性有点差(PG17dev分支)

commit b8bff07daa85c837a2747b4d35cd5a27e73fb7b2
Author: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date:   Wed Nov 8 13:30:50 2023 +0200Make ResourceOwners more easily extensible.

围绕本篇主题,后面分析这次提交前代码(PG17前的逻辑)

static void
ResourceOwnerReleaseInternal(ResourceOwner owner,ResourceReleasePhase phase,bool isCommit,bool isTopLevel)
{ResourceOwner child;ResourceOwner save;ResourceReleaseCallbackItem *item;ResourceReleaseCallbackItem *next;Datum		foundres;

resowner维护树形结构,递归释放自己的child资源。

	for (child = owner->firstchild; child != NULL; child = child->nextchild)ResourceOwnerReleaseInternal(child, phase, isCommit, isTopLevel);...

3.1 第一阶段:RESOURCE_RELEASE_BEFORE_LOCKS

  1. 事务提交时不应该有正在进行中的io了,这里需要把标志位清理干净,避免影响后面事务使用这个buffer。
  2. 清理pinned的buffer
    • 提交时不应该有pinned的了,会告警,回滚时就无所谓了,因为错误不一定出在哪,不一定给机会清理。
  3. 关闭打开的relation
    • 提交时不应该有打开的了,会告警;回滚时同上。
  4. 关闭dsm段
  5. 关闭jit context
	if (phase == RESOURCE_RELEASE_BEFORE_LOCKS){while (ResourceArrayGetAny(&(owner->bufferioarr), &foundres)){Buffer		res = DatumGetBuffer(foundres);if (isCommit)elog(PANIC, "lost track of buffer IO on buffer %d", res);AbortBufferIO(res);}while (ResourceArrayGetAny(&(owner->bufferarr), &foundres)){Buffer		res = DatumGetBuffer(foundres);if (isCommit)PrintBufferLeakWarning(res);ReleaseBuffer(res);}while (ResourceArrayGetAny(&(owner->relrefarr), &foundres)){Relation	res = (Relation) DatumGetPointer(foundres);if (isCommit)PrintRelCacheLeakWarning(res);RelationClose(res);}while (ResourceArrayGetAny(&(owner->dsmarr), &foundres)){dsm_segment *res = (dsm_segment *) DatumGetPointer(foundres);if (isCommit)PrintDSMLeakWarning(res);dsm_detach(res);}while (ResourceArrayGetAny(&(owner->jitarr), &foundres)){JitContext *context = (JitContext *) DatumGetPointer(foundres);jit_release_context(context);}......}}

3.2 第二阶段:RESOURCE_RELEASE_LOCKS

  1. 如果是顶层事务,直接释放所有锁,具体:
    • 提交时要保留会话锁,释放事务锁。事务没了会话锁还需要继续生效,生命周期比事务长。
    • 回滚时要释放所有锁。
    • 会话锁:咨询锁。
    • 事务锁:行锁、表锁等。
  2. 如果是子事务,按提交回滚做出不同行为。
    • 提交:转移锁到parent resowner。
    • 回滚:释放锁。
	else if (phase == RESOURCE_RELEASE_LOCKS){if (isTopLevel){if (owner == TopTransactionResourceOwner){ProcReleaseLocks(isCommit);ReleasePredicateLocks(isCommit, false);}}else{LOCALLOCK **locks;int			nlocks;...if (isCommit)LockReassignCurrentOwner(locks, nlocks);elseLockReleaseCurrentOwner(locks, nlocks);}}

3.3 第三阶段:RESOURCE_RELEASE_AFTER_LOCKS

  1. 释放catcache系统表缓存。
  2. 释放cached plan。
  3. 释放tuple desc,注意tuple desc在构造好后,会用IncrTupleDescRefCount函数,在resowner中记录,按引用计数控制删除。引用计数的机制主要是为了处理TupleDesc在多个地方共享使用的情况。例如一个查询的多个部分可能都需要引用同一个TupleDesc。如果在一个部分结束时就直接删除TupleDesc,那么其他部分就无法继续使用这个TupleDesc了。
  4. 释放快照。
  5. 释放fd。
	else if (phase == RESOURCE_RELEASE_AFTER_LOCKS){while (ResourceArrayGetAny(&(owner->catrefarr), &foundres)){HeapTuple	res = (HeapTuple) DatumGetPointer(foundres);if (isCommit)PrintCatCacheLeakWarning(res);ReleaseCatCache(res);}while (ResourceArrayGetAny(&(owner->catlistrefarr), &foundres)){CatCList   *res = (CatCList *) DatumGetPointer(foundres);if (isCommit)PrintCatCacheListLeakWarning(res);ReleaseCatCacheList(res);}while (ResourceArrayGetAny(&(owner->planrefarr), &foundres)){CachedPlan *res = (CachedPlan *) DatumGetPointer(foundres);if (isCommit)PrintPlanCacheLeakWarning(res);ReleaseCachedPlan(res, owner);}while (ResourceArrayGetAny(&(owner->tupdescarr), &foundres)){TupleDesc	res = (TupleDesc) DatumGetPointer(foundres);if (isCommit)PrintTupleDescLeakWarning(res);DecrTupleDescRefCount(res);}while (ResourceArrayGetAny(&(owner->snapshotarr), &foundres)){Snapshot	res = (Snapshot) DatumGetPointer(foundres);if (isCommit)PrintSnapshotLeakWarning(res);UnregisterSnapshot(res);}/* Ditto for temporary files */while (ResourceArrayGetAny(&(owner->filearr), &foundres)){File		res = DatumGetFile(foundres);if (isCommit)PrintFileLeakWarning(res);FileClose(res);}}for (item = ResourceRelease_callbacks; item; item = next){next = item->next;item->callback(phase, isCommit, isTopLevel, item->arg);}CurrentResourceOwner = save;
}

相关文章:

Postgresql源码(123)事务提交时三段资源释放分析ResourceOwnerRelease

0 总结 三段释放原因&#xff1a;因为如果先释放锁&#xff0c;没有释放一些共享资源&#xff08;比如pin住的buffer&#xff09;&#xff0c;别人拿到锁后发现我们仍然持有一些资源&#xff0c;就会有问题。所以三阶段释放主要是以锁为分界线&#xff0c;先释放锁保护的资源&…...

电脑文件误删除如何恢复?2024最新三种恢复方法

我们在使用电脑的过程中&#xff0c;随着时间的不断推移&#xff0c;渐渐的我们会发现C盘内存空间不足了。这是因为我们很多文件都默认存储在C盘&#xff0c;所以导致C盘空间不足&#xff0c;电脑运行越来越慢。那么电脑哪些文件可以删除&#xff0c;电脑删除的东西怎么恢复&am…...

Netty应用——Google Protobuf强化篇(二十)

Protobuf发送一种实例 客户端可以发送一个 Student PoJo 对象到服务器 (通过 Protobuf 编码)服务端能接收 Student PoJo 对象&#xff0c;并显示信息(通过 Protobuf 解码) Student.proto syntax "proto3"; //版本 option java_outer_classname "StudentPOJO&…...

SpringAMQP开启“可靠性”机制

前言 上一篇介绍了如何在 《SpringBoot 中集成和使用消息队列》&#xff0c;看过这一篇就基本上可以在SpringBoot中使用消息队列了&#xff0c;但是消息队列他归根结底是一个客户端服务器模式的中间件&#xff0c;面对复杂的网络环境和分布式使用环境&#xff0c;难免会出现各…...

戴尔Dell R740服务器开机冒烟亮黄灯故障维修

今天分享的是一台过保修期的DELL PowerEdge R740服务器开机冒烟的维修案例。先上图&#xff1a; 接到用户报修后工程师立即响应&#xff0c;由于用户也是刚开工第一天服务器开机就出现了这种祥龙吐雾的祥兆&#xff0c;导致工厂业务流程无法正常使用&#xff0c;这台机器在东莞…...

【阅读笔记】空域保边降噪《Side Window Filtering》

1、保边滤波背景 保边滤波器的代表包括双边滤波、引导滤波&#xff0c;但是这类滤波器有一个问题&#xff0c;它们均将待处理的像素点放在了方形滤波窗口的中心。但如果待处理的像素位于图像纹理或者边缘&#xff0c;方形滤波核卷积的处理结果会导致这个边缘变模糊。 基于这个…...

vue3前端excel导出;组件表格,自定义表格导出;Vue3 + xlsx + xlsx-style

当画面有自定义的表格或者样式过于复杂的表格时&#xff0c;导出功能可以由前端实现 1. 使用的插件 &#xff1a; sheet.js-xlsx 文档地址&#xff1a;https://docs.sheetjs.com/ 中文地址&#xff1a;https://geekdaxue.co/read/SheetJS-docs-zh/README.md xlsx-style&#…...

npm install一直卡在 sill idealTree buildDeps

当npm install命令在安装过程中卡在sill idealTree buildDeps阶段时&#xff0c;可能的原因包括网络延迟、镜像源问题或缓存问题。以下是一些可能的解决方法&#xff1a; 检查镜像源&#xff1a; 打开命令提示符&#xff08;cmd&#xff09;窗口。 输入命令npm config get…...

spring boot rabbitmq常用配置

直接上代码 package com.example.demo;import org.aopalliance.aop.Advice; import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer; import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; import org.springframewo…...

MySQL学习记录——십삼 视图及用户、权限管理

文章目录 1、视图2、用户管理3、权限管理 1、视图 视图把查询出来的结果以表结构的形式存储起来&#xff0c;视图和基表有关系&#xff0c;两者的数据变化都会互相影响。 在查询时&#xff0c;假如要经常查询一条记录&#xff0c;select …&#xff0c;那么为了方便&#xff…...

PyCharm 自动添加文件头注释

PyCharm 自动添加文件头注释 1. File and Code Templates2. Python FileReferences 1. File and Code Templates File -> Settings -> Editor -> File and Code Templates -> Python Script Reformat according to style & Enable Live Templates Created by…...

用HTML Canvas和JavaScript创建美丽的花朵动画效果

目录 一、程序代码 二、代码原理 三、运行效果 一、程序代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>炫酷花朵</title><style>* {margin: 0;padding: 0;overflow: hidden;bac…...

java----js常用的api

java----js常用的api 时间函数获取当前时间: DateUtil.today()时间偏移字符换时间格式化 map.computeIfAbsent添加list 时间函数 获取当前时间: DateUtil.today() String todayDateUtil.today()String today “2024-02-01”; 时间偏移 往前退役30天 DateUtil.offsetDay(D…...

unity 使用VS Code 开发,VS Code配置注意事项

vscode 对应的插件&#xff08;unity开发&#xff09; 插件&#xff1a;.Net Install Tool,c#,c# Dev Kit,IntelliCode For C# Dev Kit,Unity,Unity Code Snippets 本人现在是用了这些插件 unity需要安装Visual Studio Editor 1、.Net Install Tool 设置 需要在设置里面配置…...

领域驱动设计(Domain Driven Design)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、场景和要求二、领域模型关键词1.领域2.子域3.通用语言4.限界上下文5.领域模型6.实体和值对象7.聚合根8.领域服务9.领域事件 总结 前言 Domain Driven Desi…...

CF778A String Game 题解

文章目录 CF778A String Game 题解题面翻译Input DataOutput DataInput Sample 1Output Sample 1题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示算法&#xff1a;二分代码&#xff1a; CF778A String Game 题解 link 题面翻译 …...

【工具插件类教学】Unity运行时监控变量,属性,事件等的值和调用Runtime Monitoring

目录 一、介绍 二、安装方式 三、入门 1.实例化和静态成员...

实际生产中的一次非典型的基于jmeter的接口自动化实践

实际工作中遇到过一次自动化巡检的需求&#xff0c;作为测试人员没法从源代码入手&#xff0c;加之数据库也不熟悉&#xff0c;故采取接口自动化的方式来实现巡检&#xff0c;算是一种歪门邪道吧&#xff0c;应该不是接口自动化的常规使用方式。jmeter在这里的作用实际上也只是…...

新能源汽车软件开发设计规范

新能源汽车 软件开发设计规范 版本&#xff1a; 1.0 编 制&#xff1a; 校 对&#xff1a; 审 核&#xff1a; 会 签&#xff1a; …...

Linux:grep进阶(11)

Linux&#xff1a;shell脚本&#xff1a;基础使用&#xff08;4&#xff09;《正则表达式-grep工具》_shell grep 全角字符串-CSDN博客https://blog.csdn.net/w14768855/article/details/132338954?ops_request_misc%257B%2522request%255Fid%2522%253A%252217083360171680022…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...