• 自动秒收录
  • 软件:1973
  • 资讯:57811|
  • 收录网站:279872|

IT精英团

PostgreSQL并行框架分析

PostgreSQL并行框架分析

浏览次数:
评论次数:
编辑: 温瑜
信息来源: ITPUB
更新日期: 2022-05-06 18:34:31
摘要

作者简介施博文,目前就职于腾讯云PG团队概览PostgreSQL并行框架提供了一系列方便的函数,支持在插件或内核中直接调用相关函数,启动若干个后台进程进行并行操作。目前,PG的并行框架主要用来

  • 正文开始
  • 相关阅读
  • 推荐作品

作者简介

石博文,目前就职于腾讯云PG团队。

概览

PostgreSQL并行框架提供了一系列便捷的函数,支持直接在插件或内核中调用相关函数,启动多个后台进程进行并行操作。目前PG的并行框架主要用于支持并行查询。本文将介绍并行框架的相关功能,并分析其核心逻辑和功能。您可能需要知道的预先知识:

Shm_mq消息队列:PG内核提供的单生产者和单消费者消息队列的动态共享内存:简称dsm,可以在数据库操作过程中动态创建的共享内存。为什么需要并行框架设想一个场景:我们运行一条SQL,为了运行这条SQL,我们需要调用另一个后台工作器进行并行查询。为了描述方便,我们把运行这个SQL的进程称为主进程,后台工作者拉起的称为从进程。但是,当进程可能正在工作时,会出现错误甚至崩溃。这时我们需要通知主进程我们遇到了错误,让主进程处理异常。

事实上,我们可以不依赖并行框架来实现这样的功能,但这需要我们完成类似的异常处理机制。在这种情况下,直接使用并行框架会是更好的选择。此外,并行框架还提供了其他一些功能。简单总结一下:

错误处理机制:在动态共享内存中存储一个消息队列。如果从进程出现异常,将异常信息放入消息队列并发送一个信号。主进程将在检查中断时检测错误并处理异常。序列化状态同步:主进程序列化一些内容(如GUC、快照等。)并通过动态共享内存将它们传递给从属进程;用户自定义内容交付:用户可以将一些自定义数据放入动态共享内存中;安全机制:并行框架严格限制只能使用只读SQL。如果只用SQL,并行框架就安全了;但是对于内核开发者来说,在其他代码中使用并行框架需要遵守并行框架的限制。

如何使用并行框架

根据PG代码中README.parallel的介绍,使用并行框架需要遵循以下规范:

/*进入并行模式以防止不安全的调用。比如使用并行框架时发生写操作*/enter parallel ism();/* Initialize ParallelContext:存储本次并行计算的基本信息*/pcxt=createparallel context(' library _ name ',' function _ name ',nworkers);/*为自定义内容预分配空间*/SHM _ TOC _ estimate _ chunk(PCXT-estimator,size);shm _ TOC _ estimate _ keys(pcxt-estimator,keys);/*创建动态共享内存,序列化后将GUC、快照等信息复制到其中*/InitializeParallelSM(PCXT);/*将自定义内容插入动态共享内存*/space=shm _ TOC _ allocate(PCXT-TOC,size);shm_toc_insert(pcxt-toc,key,space);/*启动后台工作进程(slave process)*/launch parallel workers(pcxt);/* do parallel stuff *//*等待进程的所有退出*/WaitforParallel workerto finish(PCXT);/*从动态共享内存中读取任何最终结果

*/
/* 清理 ParallelContext */DestroyParallelContext(pcxt);
/* 退出并行模式 */ExitParallelMode();
原理分析主进程——拉起 background worker主进程在启动从进程时,会调用 LaunchParallelWorkers 函数,这个函数会调用 RegisterDynamicBackgroundWorker ,此时会给 Postmaster 进程发一个信号,请求 Postmaster 进程启动一个 background 进程,Postmaster 进程收到信号后就会启动一个新后台进程。接下来我们仔细分析一下 LaunchParallelWorkers 函数的核心代码。
voidLaunchParallelWorkers(ParallelContext *pcxt){/* 并行框架要求在不能启动从进程的情况下,也能正常运行 */if (pcxt->nworkers ==  || pcxt->nworkers_to_launch == )return;
/** 主进程需要成为 Lock Group Leader* * PG 认为:对于一个并行查询,主进程和它的从进程们为一个进程组,同一个进程组内部锁是共享的。* 即一个进程拿到 AccessExclusiveLock 的时候,同一进程组的另一个进程能拿到 AccessShareLock 锁。* 如果不这么做的话,会出现死锁。举个例子,主进程已经拿了一个 AccessExclusiveLock 锁,* 这时候从进程需要拿 AccessShareLock 才能完成工作。* 此时从进程无法拿到锁,没法结束工作;主进程因为从进程没有结束,不能释放锁,于是就 hang 住了。* 因此,并行框架引入了 lock group 的概念。同一个 lock group 中的进程不受锁排他性的影响。* 具体可参考 src/backend/storage/lmgr/README ,我会在后续的博客中介绍。*/BecomeLockGroupLeader();
/* 如果需要启动 worker 的话,必须已经注册动态共享内存了*/Assert(pcxt->seg != NULL);
/* We might be running in a short-lived memory context. */oldcontext = MemoryContextSwitchTo(TopTransactionContext);
/* worker 信息初始化 */memset(&worker, , sizeof(worker));snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",MyProcPid);snprintf(worker.bgw_type, BGW_MAXLEN, "parallel worker");worker.bgw_flags =BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION| BGWORKER_CLASS_PARALLEL;worker.bgw_start_time = BgWorkerStart_ConsistentState;worker.bgw_restart_time = BGW_NEVER_RESTART;sprintf(worker.bgw_library_name, "postgres");sprintf(worker.bgw_function_name, "ParallelWorkerMain");worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(pcxt->seg));worker.bgw_notify_pid = MyProcPid;
/** 启动进程,并行框架要求在不能启动从进程的情况下,也能正常运行。*/for (i = ; i < pcxt->nworkers_to_launch; ++i){memcpy(worker.bgw_extra, &i, sizeof(int));if (!any_registrations_failed &&RegisterDynamicBackgroundWorker(&worker,&pcxt->worker[i].bgwhandle)){shm_mq_set_handle(pcxt->worker[i].error_mqh,pcxt->worker[i].bgwhandle);pcxt->nworkers_launched++;}else{/** 即使少启动了 worker ,也能正常运行。但是需要先 detach 该 worker 的错误消息队列,否则后续我们会一直等这个 worker 启动(hang 住)。*/any_registrations_failed = true;pcxt->worker[i].bgwhandle = NULL;shm_mq_detach(pcxt->worker[i].error_mqh);pcxt->worker[i].error_mqh = NULL;}}
/** Now that nworkers_launched has taken its final value, we can initialize* known_attached_workers.*/if (pcxt->nworkers_launched > ){pcxt->known_attached_workers =palloc0(sizeof(bool) * pcxt->nworkers_launched);pcxt->nknown_attached_workers = ;}
/* Restore previous memory context. */MemoryContextSwitchTo(oldcontext);}

从进程入口——ParallelWorkerMainParallelWorkerMain 可以理解为从进程的入口函数,其函数调用栈为PostmasterMain->ServerLoop->maybe_start_bgworkers->StartBackgroundWorker->ParallelWorkerMain 。而用户定义的从进程 main 函数,将在 ParallelWorkerMain 中被调用。该函数主要就是从动态共享内存中读取一些已经序列化的主进程信息(GUC、Snapshot),成为 Lock Group Member (对应上文主进程是 Leader),然后连进数据库,通过消息队列发消息告诉主进程自己已经成功启动。
异常处理机制回到一开始的问题,如果主进程拉起 n 个 background worker 进程进行并行查询。这时候如果其中的一个出现了错误,应该如何通知主进程呢?注意,这 n 个从进程可能不是一次拉起的,可能第一次拉几个,第二次再拉几个,对应多个 ParallelContext (下文简称 pcxt)。在上文中提到,动态共享内存中存放了一个消息队列,如果从进程出现异常,将异常信息放入消息队列中并发送信号,主进程在 CHECK_FOR_INTERRUPTS 时会检测到错误,进行异常处理。事实上,主进程会维护一个 pcxt_list,对于每一个从进程,将每一个从进程的信息存放在 pcxt_list 中。在调用 CHECK_FOR_INTERRUPTS 时,其内部会调用 HandleParallelMessages 函数。如果收到了从进程发来的信号,会遍历 pcxt_list ,如对于每一个 ParallelContext ,都会检查这个 ParallelContext 启动的所有 background worker 对应的错误消息队列,如果有异常信息就从消息队列中读取信息。


总结

本文介绍了 PG 中并行框架的相关概念和设计原理,对于其中的一些细节:如 Lock Group、动态共享内存、shm_mq 消息队列并没有做具体的介绍。这些将在后续的博客中进行详细的分析。

标签:进程 框架 队列
关于数据中心最强科普 一个就给你完整了解!
« 上一篇 2022-05-06
如何用10行bash shell脚本监控Linux?
下一篇 » 2022-05-06
  • 如何在Ubuntu中保留文件系统并备份当前开发板镜像
    0阅读 0条评论 个赞
    在Ubuntu保留文件系统或者说备份当前开发板镜像的需求在不断增加。比如Ubuntu文件系统需要安装库文件的话直接使用apt-get工具就可以下载,但由于需要下载的核心板较多,比较费时间,这时需要将安……
  • 国产核心板全志T507助力消防系统升级
    0阅读 0条评论 个赞
    9月16日下午,位于湖南长沙市区内的中国电信大楼发生火灾,建筑高度218米,现场浓烟滚滚,数十层楼体燃烧剧烈。消防救援人员赶到现场后很快将火势控制住,目前大楼火势已被扑灭,所幸未发现人员伤亡。湖南电信……
  • 教大家如何处理Spring Boot易流中的用户和群体!
    0阅读 0条评论 个赞
    1.准备工作2.用户操作2.1添加用户2.2修改用户2.3删除用户2.4查询用户3.组操作3.1添加组3.2修改组3.3删除组3.4查询组4.查看表详情虽然说我们在实际开发中,……
  • 从PG15开始WAL压缩优化
    0阅读 0条评论 个赞
    PG15传闻中的超级令人激动的功能大多数跳票了,年初我也写过一个关于PG15新功能跳票的文章。PG15BETA已经发出几个月了,似乎PG15里令人激动人心的功能不多,不过从长长的新功能列表里,……
  • 深入了解美团叶子发射器开源方案
    0阅读 0条评论 个赞
    大家好,我是树哥。之前我们有聊过「如何设计一个分布式ID发号器」,其中有讲过4种解决方案,分别是:UUID类雪花算法数据库自增主键Redis原子自增美团以第2、3种解决方案为基础,开发出……
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
  • 关于Redis在windows上运行的问题和fork函数
    0阅读 0条评论 个赞
    Redis在将数据库进行持久化操作时,需要fork一个进程,但是windows并不支持fork,导致在持久化操作期间,Redis必须阻塞所有的客户端直至持久化操作完成。微软的一些工程师花费时间在解决在……
  • 用Python实现广度优先搜索
    3阅读 0条评论 个赞
    图是一种善于处理关系型数据的数据结构,使用它可以很轻松地表示数据之间是如何关联的图的实现形式有很多,最简单的方法之一就是用散列表背景图有两种经典的遍历方式:广度优先搜索和深度优先搜索。两者是相似的。实……
  • i.MX8MQ自制背板无PCIe问题详解
    9阅读 0条评论 个赞
    在飞凌嵌入式OKMX8MQ-C开发板上有两个PCIe接口,对应着两个PCIe差分时钟,两路PCIe分别用作了M.2接口卡槽KEYE(P37)和KEYM(P34)。很多使用FETMX8MQ-C核心板的用……
  • 让自己更有价值的5种能力
    0阅读 0条评论 个赞
    如何让自己更值钱?回答这个问题,需要用到黄金圈理论。什么是黄金圈理论?黄金圈理论,是国际知名营销专家、作家SimonSinek在2011年提出的,这是一种由内向外的思维模式。黄金圈理论提倡由Why、……
  • python入门系列(十)学习Python文件处理
    0阅读 0条评论 个赞
    文件处理在Python中处理文件的关键函数是open()函数。有四种不同的方法(模式)来打开一个文件"r"-读取-默认值。打开一个文件进行读取,如果文件不存在则出错。"a"-Append……
  • Linux环境程序如何运行?
    0阅读 0条评论 个赞
    .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
  • 三万字肝爆《数据仓库体系》
    0阅读 0条评论 个赞
    文章很长,前言一定要看拥有本篇文章,意味着你拥有一本完善的书籍,本篇文章整理了数据仓库领域,几乎所有的知识点,文章内容主要来源于以下几个方面:源于「数据仓库交流群」资深数据仓库工程师的交流讨论,如《s……
  • 构建docker镜像库(1):用注册表构建本地镜像库
    0阅读 0条评论 个赞
    目录一.系统环境二.前言三.使用registry搭建私有镜像仓库3.1环境介绍3.2k8smaster节点配置镜像仓库3.3k8sworker1节点配置从私有仓库上传和拉取镜像3.3.1上传镜……
  • SpringMVC 03: 请求和响应的乱码解决 + SpringMVC响应Ajax请求
    1阅读 0条评论 个赞
    请求或响应的中文乱码问题tomcat9解决了get请求和响应的中文乱码问题,但是没有解决post请求或响应的中文乱码问题tomcat10解决了get和post请求以及响应的中文乱码问题考虑到实际项目中……
  • Java线程面试题前50名
    0阅读 0条评论 个赞
    .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
  • 渗透攻击和防御网络-简单的SQL注入
    0阅读 0条评论 个赞
    1背景京东SRC(SecurityResponseCenter)收录大量外部白帽子提交的sql注入漏洞,漏洞发生的原因多为sql语句拼接和Mybatis使用不当导致。2手工检测2.1前置知识……
  • 大促销活动如何抵御高流量DDoS攻击?
    0阅读 0条评论 个赞
    大促活动如何抵御大流量DDoS攻击?每一次活动大促带来的迅猛流量,对技术人而言都是一次严峻考验。如果在活动期间遭受黑产恶意DDoS攻击,无疑是雪上加霜。电商的特性是业务常态下通常不会遭受大流量DD……
  • 基于位置变化的市县弹出引导切换
    31阅读 0条评论 个赞
    目录1.背景2.模型方案产出3.总结01背景58App业务中有城市和县域两个首页,两者中间有一个过渡选择页,用户通过点击该页面下的条目内容可以切换到对应条目的首页;比如:点击“北京”会跳转到北京(市)……
  • SQL Server批量完整备份
    0阅读 0条评论 个赞
    一.本文所涉及的内容(Contents)本文所涉及的内容(Contents)背景(Contexts)实现代码(SQLCodes)实现方式一(One)实现方式二(Two)实现方式三(Three)参考文……
  • springboot集成docsify实现可移植文档
    0阅读 0条评论 个赞
    需求分析文档可以和项目一起进行版本管理文档可以在线访问文档可以与springboot项目集成,不需要分开部署MarkDown支持文档跟随,打包jar也可以访问技术选型对于网上已有的方案,大致分为如下几……
  • Python入门系列(七)开发常说的"累"与"对象"
    0阅读 0条评论 个赞
    类与对象Python是一种面向对象的编程语言。要创建类,请使用关键字classclassMyClass:x=5创建一个名为p1的对象,并打印x的值p1=MyClass()print(p1……
  • MySQL查询性能优化指数下推的七大武器
    0阅读 0条评论 个赞
    前面已经讲了MySQL的其他查询性能优化方式,没看过可以去了解一下:MySQL查询性能优化七种武器之索引潜水MySQL查询性能优化七种武器之链路追踪今天要讲的是MySQL的另一种查询性能优化方式—索……
  • SQL Server表变量和临时表的区别
    0阅读 0条评论 个赞
    一、表变量表变量在SQLServer2000中首次被引入。表变量的具体定义包括列定义,列名,数据类型和约束。而在表变量中可以使用的约束包括主键约束,唯一约束,NULL约束和CHECK约束(外键……
  • 新一代网络请求库:python-httpx库
    0阅读 0条评论 个赞
    目录httpx库一、概述1、简介2、命令行模式3、快速开始3.1get请求3.2post请求3.2.1表单3.2.2文件3.2.3JSON3.2.4二进制3.3响应处理3.4流……
  • 全网最全Linux命令汇总!(史上最全 推荐收藏)
    7阅读 0条评论 个赞
    今天,给小伙伴们带来一篇史上最全Linux命令总结的文章,命令有点多,建议小伙伴们先收藏后阅读。好了,我们开始今天的正文。列出目录内容ls-a:显示所有文件(包括隐藏文件);ls-l:显示详细……
最近发布资讯
更多