【PostgreSQL的insert语句执行过程分析】

  • Post author:
  • Post category:其他


在数据库的使用中,增删改查这种操作每天都在进行,本文通过gdb工具演示了一个insert语句的执行流程。

一、gdb增加断点

开启一个session,获取pid

另开一个窗口,用gdb进入调试状态

数据库端执行插入操作,因为gdb绑定了pid,会卡住,直到随着gdb的调试过程,执行到真正插入动作的函数

我在gdb端加了总共四个断点

二、执行到exec_simple_query()

先从当前位置开始连续运行程序,到第一个断点,从下往上看运行的堆栈:

可以看到,insert动作从main()函数开始,首先到了postmaster进程入口 PostmasterMain() ,通过ServerLoop() 监听session连接并fork postgres子进程 ,然后用BackendStartup()启动backend进程 ,之后到PostgresMain() 即backend的入口,通过子进程backend获取sql语句 ,并最终到了exec_simple_query() 即SQL引擎的入口。

可以在此时查看传入这里的参数

单步执行,查看执行过程中相关变量的值。

三、执行到ProcessQuery()

c继续执行,在下一个断点,即ProcessQuery()这里停下,查看堆栈,可以看到这一部分跑到了PortalRun()的入口,Portal是查询执行器的四个主要子模块之一,也通常被叫做策略选择模块,在这选择执行策略后,会将控制流程交给相应的处理部件,即Executer或者ProcessUtility。这里根据策略调用了PortalRunMulti() ,最后到达了ProcessQuery()。

我们继续单步执行,ProcessQuery()在这一部分创建QueryDesc,它封装了执行器执行查询所需的所有内容 ,调用ExecutorStart函数初始化结构体EState ,ExecutorStart函数调用InitPlan初始化计划状态树 。

这一部分执行流程过程如黄色所示:

四、执行到standard_ExecutorRun()

继续c执行,到了standard_ExecutorRun(),这里是先通过ExecutorRun ()这里进行判断,如果有hook函数,就执行hook函数,没有的话,执行标准函数standard_ExecutorRun()。(比较典型的使用hook的是pg_show_plans插件)

继续执行,最后通过standard_ExecutorRun()的ExecutePlan()执行insert并通过MemoryContextSwitchTo()切换回原内存上下文。

c继续执行一直到结束

可以在数据库端看到数据成功插入

整个插入动作的堆栈如下:



版权声明:本文为weixin_47308871原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。