▲ 进阶篇
文章平均质量分 92
相较于初阶篇内容,该专栏的系列文章涉及到的知识点难度会更高、内容会更广、更深。主要讲解PG内核中索引(索引原理、索引分类、各索引特点等)、查询编译(查询分析、查询重写、查询规划等)、查询执行等知识,同时会讲解编译原理相关知识。通过本专栏的系统学习,能够快速让你成为一名高级DBA。
优惠券已抵扣
余额抵扣
还需支付
¥99.90
购买须知?
本专栏为图文内容,最终完结不会低于15篇文章。
订阅专栏,享有专栏所有文章阅读权限。
本专栏为虚拟商品,基于网络商品和虚拟商品的性质和特征,专栏一经购买无正当理由不予退款,不支持升级,敬请谅解。
内核之道
某大厂资深全栈工程师,专注于『PostgreSQL内核、NVR、AI超脑、智能应用服务器』开发
展开
-
【0273】深入分析 relcache(relation descriptor cache)初始化第一阶段(1)
本文是的前传。本文主要内容将详细讲解PG内核中初始化relcache时,其第一阶段主要负责完成的任务是什么?以及该阶段完成了什么功能。对于第一阶段:这将初始化关系表描述符缓存。在调用这个函数的时候,我们还不能访问数据库(主要是因为事务子系统还没有启动);我们所做的就是创建一个空的缓存哈希表。这必须在开始初始化事务之前完成,否则如果事务在我们可以设置relcache之前终止,会崩溃。原创 2024-03-19 20:15:21 · 52 阅读 · 0 评论 -
【0268】深入分析PG内核 shared PGPROC array(ProcArrayStruct、procArray)初始化机制
在【0267】pg内核初始化 process table(ProcGlobal、PROC_HDR、PGPROC)分析一文中,深入分析了PG内核初始化进程表(process table)的过程、实现。本文将在此基础上深入分析共享PGPROC数组(shared PGPROC array)的初始化过程,以及该数组作用。(1)PGPORC array的数据类型、各成员变量含义(2)PGPROC array初始化过程(3)PGPROC array作用。原创 2024-02-27 14:50:56 · 73 阅读 · 0 评论 -
【0267】pg内核初始化 process table(ProcGlobal、PROC_HDR、PGPROC)分析
在postmaster或standalone后端启动期间初始化全局进程表(global process table)。原创 2024-02-24 16:44:25 · 295 阅读 · 0 评论 -
【0264】深入分析relcache(relation descriptor cache)缓存初始化第2阶段(2)
relcache意味着pg在内存中缓存一份关系表描述符。阶段1、阶段2、阶段3均在InitPostgres()中完成初始化操作。本文主要讲relcache初始化的第二阶段内容。原创 2024-02-23 14:28:24 · 64 阅读 · 0 评论 -
【0263】深入分析pg内核 Parse tree(解析树)到Query tree(查询树)的转换实现
本文是的续篇,重点在于分析pg内核是如何完成将原始解析数(raw parse tree)转换为Query Tree(查询树)的过程。原创 2024-02-22 10:32:27 · 311 阅读 · 0 评论 -
【0261】Postgres内核 raw parsetree 深入分析(1)
pg内核完成原始解析树(raw parsetree)相关功能入口是exec_simple_query()函数,该函数位于postgres.c(src/backend/cop )。原创 2024-02-21 16:56:43 · 390 阅读 · 0 评论 -
【0260】pg_filenode.map文件分析(内含map文件读取、解析demo)
map文件是关键数据:我们没有从丢失或损坏中恢复的自动方法。我们使用CRC来检测损坏。为了最小化更新失败的风险, map文件应该保持在不超过一个标准大小的磁盘扇区(即512字节(bytes)),并且我们使用就地覆盖而不是玩重命名游戏。下面的结构布局被设计为恰好占用512字节,这可能会使文件系统更新更有效率。数组中的条目没有特定的顺序。我们可以通过坚持OID顺序来加快搜索速度,但考虑到映射集的预期大小,这真的不值得麻烦。原创 2024-02-19 17:02:57 · 368 阅读 · 0 评论 -
【0256】揭晓pg内核中MyBackendId的分配机制(后端进程Id,BackendId)(二)
在【0255】揭晓pg内核中MyBackendId的分配机制(后端进程Id,BackendId)(一)中,详细讲解了BackendId和shmInvalBuffer,以及全局指针变量shmInvalBuffer的初始化过程、最终初始化后各成员变量值。而pg内核为后端进场分配BackendId是基于shmInvalBuffer所执行的共享内存,因此上一篇文章是前提。原创 2024-02-05 15:00:05 · 703 阅读 · 0 评论 -
【0255】揭晓pg内核中MyBackendId的分配机制(后端进程Id,BackendId)(一)
MyBackendId的数据类型是BackendId),它表示“当前活动的后端进程的唯一标识符”。(1)BackendId是唯一的,即多个后端进场,各自的BackendId(MyBackendId)是不相同的(2)后端进程被kill掉,自动关闭退出后,该BackendId将会被释放本文的重点内容是分析pg内核如何去为每个后端进场分配这个BackendId,通过结合源码的方式,详细分析其底层的分配过程。BackendId是如何为每个后端进场分配的?原创 2024-02-05 10:59:13 · 548 阅读 · 0 评论 -
【0251】如何让pg生成core文件,并通过gdb工具定位到pg服务异常崩溃点(精确到函数行)
一些不经意的因素、操作,总会让PostgreSQL服务异常崩溃。这些报错日志都意味着pg服务异常崩溃停止了(问题很严重)。而pg的log文件往往只有这些简单的提示打印,仅依赖这些提示,是无法定位到具体问题所在的。除非你精通pg源码,所有源码滚瓜烂熟;很显然,是无法做到这一点的。那么面对这样的崩溃问题,要如何去定位崩溃原因,是一个比较困难的话题。如果有方法能够找到崩溃根源,且精确到pg源码中的某个函数的某一行,那可就太棒了。本文内容是作者多年下来总结出的经验,真实可靠、有效。原创 2024-01-25 16:24:07 · 292 阅读 · 0 评论 -
【0250】深入分析Write-Ahead Log Fault Tolerance(WAL容错)
本文将详细讲解影响。原创 2024-01-23 12:50:54 · 279 阅读 · 0 评论 -
【0247】PG内核checkpoint实现机制分析(2)
为了在失败后恢复数据一致性(即执行恢复),PostgreSQL必须在正向方向上重放WAL,并将代表丢失更改的条目应用于相应的页面。为了找出丢失的内容,将存储在磁盘上的页面的LSN与WAL条目的LSN进行比较。但我们应该从什么时候开始恢复呢?如果我们开始得太晚,在此之前写入磁盘的页面将无法接收到所有更改,这将导致不可逆转的数据损坏。从头开始是不现实的:不可能存储如此庞大的潜在数据量,也不可能接受如此长的恢复时间。我们需要一个逐渐向前移动的检查点,这样可以安全地从该点开始恢复并删除所有以前的WAL条目。原创 2024-01-22 08:50:00 · 224 阅读 · 0 评论 -
【0238】flex/yacc之PG内核parser
该目录不仅仅对SQL查询进行标记和解析。它还为传递给优化器和执行器的各种复杂查询创建查询结构。src下的parser目录:。此目录下的源文件列表:include下的parser目录。原创 2023-11-27 12:47:40 · 108 阅读 · 0 评论 -
【0236】聊一聊PG内核中的命令标签(Command Tags、CommandTag、tag_behavior)
1. 什么是命令标签(Command Tags)当客户端向PG服务下发一个请求时,postgres进程在读取到用户的请求缓冲区之后,需要对从中解析出用户的具体请求,比如:CREATE TABLE、CREATE DATABASE、DROP TABLE、SELECT等具体操作,这里除了会用到后面即将讲的词法分析解析器flex之外,还会用到一个很重要的模块(tcop, 完整路径如下:src/include/tcop),该路径下的头文件定义了PG数据库内核所能够识别到的所有SQL关键词。1.1 命令标签列表相原创 2023-11-21 13:35:16 · 764 阅读 · 0 评论 -
【0235】修改私有内存(private memory)中的MyBEEntry时,st_changecount值前后变化
上一篇: 【0234】PgBackendStatus 记录当前postgres进程的活动状态客户端(eg:psql)在连接上postmaster之后,postmaster守护进程会fork()一个后端进场(backend process),之后此客户端的所有操作、交互均有此对应的BackendId进程接收、响应。客户端的每一个SQL操作语句,在pg_stat_activity()函数中都可以看到其完整的消息,比如:语句操作时间、当前操作的SQL语句、当前backend process的运行状态等等。此函数中原创 2023-11-17 11:43:06 · 284 阅读 · 0 评论 -
【0232】通过PG log分析事务系统(StartTransaction)的运行情况
如果有嵌套,存在父事务,则递归调用函数:ShowTransactionStateRec()打印所以事务XID信息。如果当前事务系统有嵌套级别,即存在子事务,则循环遍历打印子事务的XID信息。有了事务运行状态相关的日志信息后,接下来的重点就是如何去理解这些日志打印所代表的具体含义。log文件默认会打印(只要日志打印级别<=DEBUG5)事务相关的日志信息。【由于这里无事务嵌套,所以仅打印当前事务的状态、XID、subid、cid等数据】这便是当前log文件中事务相关的日志所表示的信息。原创 2023-10-30 19:58:52 · 116 阅读 · 0 评论 -
【0230】Postgres内核事务(transaction)系统实现原理之层次划分(上)
事务是如何工作?接下来让我们通过gdb方式来跟踪一下PG内核中事务的底层工作原理。BEGINCOMMITABORTxactxact.c函数。原创 2023-10-27 16:55:03 · 134 阅读 · 0 评论 -
【0222】存储管理器smgr设计机制,及SMgrRelation、SMgrRelationData的作用(1)
在一文的“”章节中,详细讲解了PG内核中VFD(虚拟文件描述符)的实现原理。本文开始,将来讲解PG内核中另外一个非常重要的知识点,即PG内核的存储管理器 ----- 磁盘介质管理器(SMGR)。这也是PG内核中非常非常重要的一个知识点。一文曾详细分析过,PG数据库中的关系表是以文件的形式存储于PGDATA目录下,表文件默认大小是1GB,当表文件大小超过1GB后,会被切割成多个大小1GB的文件。存储管理器SMGR能够实现了什么功能?学完SMGR章节的内容后,对理解PG内核有和帮助?原创 2023-09-22 21:19:30 · 229 阅读 · 0 评论 -
【0220】stats collector如何得知pgStatSock中的消息类型、消息报文内容以及消息是否完整?
前面已经图文并茂的讲解过,stats collector进程通过UDP方式与其他进程进行通信,在初始化资源时,通过socket()系统函数得到一个全局套接字fd。后续其他进程有统计消息时,通过该句柄,可发送消息给到stats collector。原创 2023-09-05 16:20:44 · 341 阅读 · 0 评论 -
【0219】一文搞懂PostgreSQL中global.stat、global.tmp、db_*.stat等统计文件的格式,及文件组成原理
文件是一个重要的统计文件,用于存储全局的统计信息。文件通常位于 PostgreSQL 数据目录中,与控制文件和其他系统文件一起存储。一文中有详细讲解过,PG内核中,数据库表、索引表、数据库等都是以OID命名的。对于需要进行写统计文件的数据库,这里的。如果文件描述符申请成功,则继续下面的统计文件处理;在写入统计信息之前,确保已经更新统计信息并将它们保存在内存中的统计对象中。文件需要适当的权限。函数,该函数将(DEBUG2级别)打印global.stat统计文件的信息(即先把所有相关的统计信息写到此文件中。原创 2023-08-31 20:47:34 · 213 阅读 · 0 评论 -
【0217】stats collector(统计信息收集器)进程启动原理(1)
本文接下来将详细讲解PG内核是如何完成stats collector进程的启动过程,以及该进程是如何完成统计信息的收集实现原理。基于种种原因,我们需要考虑到stats collector进程退出、挂掉的情形,这时就有一个问题需要重视,即以什么样的周期、频率去检查、启动此进程。PgstatCollectorMain(0, NULL)函数完成stats collector进程的主要启动过程,由于该函数的函数体代码量较大,因此,将拆开来放在下一文中进行讲解。回调来执行此操作)。函数,完成子进程的创建过程。原创 2023-08-28 14:48:59 · 184 阅读 · 0 评论 -
【0216】stats collector(统计信息收集器)资源初始化之获取IPV4套接字地址信息(2)
一文的2.1.3节中讲解了stats collector进程会创建UDP,与其他进程进行通信,从而实现收集信息的目的。上一篇文章中,提到了PG内核在创建UDP套接字时,需要先获取当前设备的ipv4地址信息,然后顺便也用。PG内核中也是通过封装这个接口去完成的获取ipv4地址信息的功能。这个库函数演示了一下通道域名获取ip地址的过程。原创 2023-08-16 15:58:10 · 209 阅读 · 0 评论 -
【0213】pg_hba.conf以password作为认证证方式下,frontend如何处理来自Backend的请求认证报文
相关阅读:★★。原创 2023-06-27 20:32:03 · 220 阅读 · 0 评论 -
【0212】tcpdump抓包分析pg_hba.conf以password作为认证证方式下frontend与Backend之间身份验证过程(13 - 2)
中的密码hash,会进行一个校验过程。其校验结果有两种,校验通过,校验失败。本文将详细讲解着两种情况下,PG内核中Backend内部如何应对、如何去处理。在上一节内容中,讲解了Backend对于接收到来自frontend的字符串明文密码,和来自于来自。等系列文章中有进行过详细的讲解。如果密码校验通过,则走。如果密码校验失败,则走。原创 2023-06-27 14:40:34 · 321 阅读 · 0 评论 -
【0211】tcpdump抓包分析pg_hba.conf以password作为认证证方式下frontend与Backend之间身份验证过程(13 - 1)
下的frontend与Backend进程之间的通信过程。结合抓包方式,分析了Backend进程向frontend、frontend向Backend进程等发送的报文,以及各自报文中的详细内容。本文开始,将通过tcpdump抓包分析,结合源码方式,详细讲解当PG数据库在。在前面的几篇文章中,详细讲解了PG数据库在。这个认证过程和前面那几篇文章中讲解的。认证方式下的交互过程一致。原创 2023-06-19 19:09:43 · 1241 阅读 · 5 评论 -
【0210】frontend接收到Backend进程的认证请求报文后,如何作出回应 (12)
一文中,我们讲解了客户端接收到后端进程发送的认证请求报文后,从中解析出了第一部分和第二部分数据;接下来还需要从接收到的套接字缓冲区中解析出来第三部分数据,从而验证后端进程发送的消息体是完整。如果认证请求报文类型是AUTH_REQ_OK,则第三部分数据后面是没有额外数据的。下图为Backend进程组装认证请求报文的过程,额外数据参数为NULL,长度为0。如果读取出来的请求类型是MD5请求,,请确保密码salt在输入缓冲区中。这里的读取请求认证类型,即读取上图中蓝色标注的部分数据(),仍然是通过调用函数。原创 2023-06-17 17:25:22 · 318 阅读 · 1 评论 -
【0209】frontend如何接收来自Backend进程的认证请求报文(authentication request packet)(11)
上面列出的几点内容已经通过那三篇文章进行了详细的分析与讲解;接下来要做的就是理解前端(本文中所有前端均指。这个状态是接下来理解客户端接收并解析Backend进程发送过来的请求认证消息的关键。这篇文章必须得理解,注意是要理解,而不是走马观花过一遍。成员变量的状态变化是非常、非常、非常。之重要的,不理解这张图中。接下来本文的内容将重点围绕着上面的这几个点开始逐一讲解。的变化过程,那么阅读接下来的内容将会非常费劲。要理解接下来的内容,原创 2023-06-16 19:49:42 · 605 阅读 · 0 评论 -
【0208】Backend向客户端发送Client authentication的底层实现(10 - 3)
理解Backend进程如何向客户端发送消息的过程是非常重要的。它并非直接调用类似send()、sendto()、write()等系统函数向前端(所有客户端统称为前端)发送。而是按照约定格式拼接报文、然后拷贝到全局缓冲区、再发送给客户端这样的一个过程。其拼接过程和本文的1.2.1.1节的过程一样,因为都是同一个函数。显然该字符是作为整个完整数据包的第一各(部分)发送给前端的。【此函数非常非常之重要!条件,所以第二步要执行的为下面截图中红色线框标注处的逻辑。,并且该变量中的成员使用默认的函数进行初始化操作。原创 2023-06-15 18:43:32 · 463 阅读 · 0 评论 -
【0207】Backend向客户端发送Client authentication的底层实现(10 - 2)
与客户端的验证交互。因为postmaster进程只负责接收来自客户端的连接请求,并为其fork()一个后端进程,而之后的身份验证交互过程,均由此后端进程进行交互。前面标题说的是postmaster向客户端发送验证结果,准确来说,应该是后端进程。如果客户端发送的认证方式(pg_hba.conf)通过认证,则其对应状态码是。本文讲解的内容就是在此状态码下向客户端发送认证报文的过程。此处向客户端发送认证请求报文时,该函数的第三、四个参数分别填。下面将对该函数的内部实现(即发生过程)展开详细进行讲解。原创 2023-06-15 12:18:44 · 1551 阅读 · 0 评论 -
【0206】Backend 向客户端发送身份认证请求报文(Client authentication) (10 - 1)
postmaster守护进程的初始化顺序如下所示,相较于backend process,过程要简单些,只需要下面main()、PostmasterMain()这两个函数的调用就可以完成postmaster进程的创建。),该数据类型里面的成员分别记录了此socket连接的套接字句柄fd、fd是否阻塞方式、客户端IP、客户端port、客户端数据包协议(2.0还是3.0)、连接的数据库名、用户名、hba认证信息、是否启用SSL等等。语句针对不同的验证方式,而不同的方式又分别调用了不同的函数实现。原创 2023-06-13 18:11:16 · 1588 阅读 · 0 评论