PostgreSQL的insert語句執行過程分析

T1YSL發表於2022-03-18

在資料庫的使用中,增刪改查這種操作每天都在進行,本文透過gdb工具演示了一個insert語句的執行流程。

一、gdb增加斷點

開啟一個session,獲取pid
1647521753323.png

另開一個視窗,用gdb進入除錯狀態

1647521868566.png

資料庫端執行插入操作,因為gdb繫結了pid,會卡住,直到隨著gdb的除錯過程,執行到真正插入動作的函式

1647521904969.png

我在gdb端加了總共四個斷點
1647524623688.png

二、執行到exec_simple_query()

先從當前位置開始連續執行程式,到第一個斷點,從下往上看執行的堆疊:

1647524767084.png

可以看到,insert動作從main()函式開始,首先到了postmaster程式入口 PostmasterMain() ,透過ServerLoop() 監聽session連線並fork postgres子程式 ,然後用BackendStartup()啟動backend程式 ,之後到PostgresMain() 即backend的入口,透過子程式backend獲取sql語句 ,並最終到了exec_simple_query() 即SQL引擎的入口。

可以在此時檢視傳入這裡的引數
1647526102468.png

單步執行,檢視執行過程中相關變數的值。
1647526543774.png

三、執行到ProcessQuery()

c繼續執行,在下一個斷點,即ProcessQuery()這裡停下,檢視堆疊,可以看到這一部分跑到了PortalRun()的入口,Portal是查詢執行器的四個主要子模組之一,也通常被叫做策略選擇模組,在這選擇執行策略後,會將控制流程交給相應的處理部件,即Executer或者ProcessUtility。這裡根據策略呼叫了PortalRunMulti() ,最後到達了ProcessQuery()。
1647527251161.png

我們繼續單步執行,ProcessQuery()在這一部分建立QueryDesc,它封裝了執行器執行查詢所需的所有內容 ,呼叫ExecutorStart函式初始化結構體EState ,ExecutorStart函式呼叫InitPlan初始化計劃狀態樹 。
1647529515600.png

這一部分執行流程過程如黃色所示:
1647528024796.png

四、執行到standard_ExecutorRun()

繼續c執行,到了standard_ExecutorRun(),這裡是先透過ExecutorRun ()這裡進行判斷,如果有hook函式,就執行hook函式,沒有的話,執行標準函式standard_ExecutorRun()。(比較典型的使用hook的是pg_show_plans外掛)
1647530334528.png

繼續執行,最後透過standard_ExecutorRun()的ExecutePlan()執行insert並透過MemoryContextSwitchTo()切換回原記憶體上下文。
1647530791018.png

c繼續執行一直到結束

1647531040313.png

可以在資料庫端看到資料成功插入
1647531072246.png

整個插入動作的堆疊如下:
1647531572570.png


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69990629/viewspace-2871958/,如需轉載,請註明出處,否則將追究法律責任。

相關文章