PostgreSQL 原始碼解讀(15)- Insert語句(執行過程跟蹤)
本文簡單介紹了PG INSERT語句的執行全過程,包括使用gdb跟蹤除錯的全過程,重點的資料結構等。
一、呼叫棧
INSERT語句的函式呼叫棧:
(gdb) bt
#0 PageAddItemExtended (page=0x7feaaefac300 "\001", item=0x29859f8 "2\234\030", size=61, offsetNumber=0, flags=2) at bufpage.c:196
#1 0x00000000004cf4f9 in RelationPutHeapTuple (relation=0x7feac6e2ccb8, buffer=141, tuple=0x29859e0, token=false) at hio.c:53
#2 0x00000000004c34ec in heap_insert (relation=0x7feac6e2ccb8, tup=0x29859e0, cid=0, options=0, bistate=0x0) at heapam.c:2487
#3 0x00000000006c076b in ExecInsert (mtstate=0x2984c10, slot=0x2985250, planSlot=0x2985250, estate=0x29848c0, canSetTag=true) at nodeModifyTable.c:529
#4 0x00000000006c29f3 in ExecModifyTable (pstate=0x2984c10) at nodeModifyTable.c:2126
#5 0x000000000069a7d8 in ExecProcNodeFirst (node=0x2984c10) at execProcnode.c:445
#6 0x0000000000690994 in ExecProcNode (node=0x2984c10) at ../../../src/include/executor/executor.h:237
#7 0x0000000000692e5e in ExecutePlan (estate=0x29848c0, planstate=0x2984c10, use_parallel_mode=false, operation=CMD_INSERT, sendTuples=false, numberTuples=0, direction=ForwardScanDirection,
dest=0x2990dc8, execute_once=true) at execMain.c:1726
#8 0x0000000000690e58 in standard_ExecutorRun (queryDesc=0x2981020, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:363
#9 0x0000000000690cef in ExecutorRun (queryDesc=0x2981020, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:306
#10 0x0000000000851d84 in ProcessQuery (plan=0x2990c68, sourceText=0x28c5ef0 "insert into t_insert values(9,'11','12','13');", params=0x0, queryEnv=0x0, dest=0x2990dc8, completionTag=0x7ffdbc052d10 "")
at pquery.c:161
#11 0x00000000008534f4 in PortalRunMulti (portal=0x292b490, isTopLevel=true, setHoldSnapshot=false, dest=0x2990dc8, altdest=0x2990dc8, completionTag=0x7ffdbc052d10 "") at pquery.c:1286
#12 0x0000000000852b32 in PortalRun (portal=0x292b490, count=9223372036854775807, isTopLevel=true, run_once=true, dest=0x2990dc8, altdest=0x2990dc8, completionTag=0x7ffdbc052d10 "") at pquery.c:799
#13 0x000000000084cebc in exec_simple_query (query_string=0x28c5ef0 "insert into t_insert values(9,'11','12','13');") at postgres.c:1122
#14 0x0000000000850f3c in PostgresMain (argc=1, argv=0x28efaa8, dbname=0x28ef990 "testdb", username=0x28ef978 "xdb") at postgres.c:4153
#15 0x00000000007c0168 in BackendRun (port=0x28e7970) at postmaster.c:4361
#16 0x00000000007bf8fc in BackendStartup (port=0x28e7970) at postmaster.c:4033
#17 0x00000000007bc139 in ServerLoop () at postmaster.c:1706
#18 0x00000000007bb9f9 in PostmasterMain (argc=1, argv=0x28c0b60) at postmaster.c:1379
#19 0x00000000006f19e8 in main (argc=1, argv=0x28c0b60) at main.c:228
二、跟蹤分析
插入測試資料:
testdb=# -- 獲取pid
testdb=# select pg_backend_pid();
pg_backend_pid
----------------
1610
(1 row)
testdb=# -- 插入1行
testdb=# insert into t_insert values(25,'insert','insert','insert');
(掛起)
啟動gdb,跟蹤除錯:
[root@localhost ~]# gdb -p 3294
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
...
#設定斷點
(gdb) b PostgresMain
Breakpoint 1 at 0x8507bb: file postgres.c, line 3631.
(gdb) b exec_simple_query
Breakpoint 2 at 0x84cad8: file postgres.c, line 893.
(gdb) b PortalRunMulti
Breakpoint 3 at 0x8533df: file pquery.c, line 1210.
…
(gdb) c
Continuing.
Breakpoint 2, exec_simple_query (
query_string=0x219cef0 "insert into t_insert values(25,'insert','insert','insert');") at postgres.c:893
893 CommandDest dest = whereToSendOutput;
#PostmasterMain 的除錯需要使用fork process的方式進行,不是重點,暫時不作介紹
#進入exec_simple_query
#輸入引數:query_string=0x219cef0 "insert into t_insert values(25,'insert','insert','insert');"
#生成解析列表,解析列表parsetree_list中的元素型別為RawStmt
#INSERT語句,RawStmt的NodeType=T_InsertStmt
(gdb)
944 parsetree_list = pg_parse_query(query_string);
(gdb) p *parsetree_list
$11 = {type = T_List, length = 1, head = 0x219dce0, tail = 0x219dce0}
(gdb) p *(RawStmt *)(parsetree_list->head->data.ptr_value)
$12 = {type = T_RawStmt, stmt = 0x219dc60, stmt_location = 0, stmt_len = 58}
(gdb) p *((RawStmt *)(parsetree_list->head->data.ptr_value))->stmt
$13 = {type = T_InsertStmt}
#生成查詢列表querytree_list,其中的元素為Query
(gdb)
1047 querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
(gdb) p *(Query *)(querytree_list->head->data.ptr_value)
$14 = {type = T_Query, commandType = CMD_INSERT, querySource = QSRC_ORIGINAL, queryId = 0, canSetTag = true,
utilityStmt = 0x0, resultRelation = 1, hasAggs = false, hasWindowFuncs = false, hasTargetSRFs = false,
hasSubLinks = false, hasDistinctOn = false, hasRecursive = false, hasModifyingCTE = false,
hasForUpdate = false, hasRowSecurity = false, cteList = 0x0, rtable = 0x219e260, jointree = 0x21c2a50,
targetList = 0x21c2ad0, override = OVERRIDING_NOT_SET, onConflict = 0x0, returningList = 0x0,
groupClause = 0x0, groupingSets = 0x0, havingQual = 0x0, windowClause = 0x0, distinctClause = 0x0,
sortClause = 0x0, limitOffset = 0x0, limitCount = 0x0, rowMarks = 0x0, setOperations = 0x0,
constraintDeps = 0x0, withCheckOptions = 0x0, stmt_location = 0, stmt_len = 58}
(gdb) p *querytree_list
$15 = {type = T_List, length = 1, head = 0x21c2b80, tail = 0x21c2b80}
#檢視Query中的元素
#rtable,List中的實際型別為RangeTblEntry,可以理解為實際的資料表
(gdb) p *((Query *)(querytree_list->head->data.ptr_value))->rtable
$16 = {type = T_List, length = 1, head = 0x219e240, tail = 0x219e240}
(gdb) p *(RangeTblEntry *)((Query *)(querytree_list->head->data.ptr_value))->rtable->head->data.ptr_value
$17 = {type = T_RangeTblEntry, rtekind = RTE_RELATION, relid = 26731, relkind = 114 'r', tablesample = 0x0,
subquery = 0x0, security_barrier = false, jointype = JOIN_INNER, joinaliasvars = 0x0, functions = 0x0,
funcordinality = false, tablefunc = 0x0, values_lists = 0x0, ctename = 0x0, ctelevelsup = 0,
self_reference = false, coltypes = 0x0, coltypmods = 0x0, colcollations = 0x0, enrname = 0x0,
enrtuples = 0, alias = 0x0, eref = 0x219e060, lateral = false, inh = false, inFromCl = false,
requiredPerms = 1, checkAsUser = 0, selectedCols = 0x0, insertedCols = 0x21c28e8, updatedCols = 0x0,
securityQuals = 0x0}
#jointree為NULL
(gdb) p *((Query *)(querytree_list->head->data.ptr_value))->jointree
$18 = {type = T_FromExpr, fromlist = 0x0, quals = 0x0}
#targetList是輸出的目標Entry(資料列)
(gdb) p *(TargetEntry *)((Query *)(querytree_list->head->data.ptr_value))->targetList->head->data.ptr_value
$20 = {xpr = {type = T_TargetEntry}, expr = 0x219e590, resno = 1, resname = 0x219e2e0 "id",
ressortgroupref = 0, resorigtbl = 0, resorigcol = 0, resjunk = false}
(gdb) n
1054 if (snapshot_set)
#生成PlannedStmt列表
(gdb) p *plantree_list
$21 = {type = T_List, length = 1, head = 0x225e488, tail = 0x225e488}
(gdb) p *(PlannedStmt *)(plantree_list->head->data.ptr_value)
$22 = {type = T_PlannedStmt, commandType = CMD_INSERT, queryId = 0, hasReturning = false,
hasModifyingCTE = false, canSetTag = true, transientPlan = false, dependsOnRole = false,
parallelModeNeeded = false, jitFlags = 0, planTree = 0x225dfe8, rtable = 0x225e2a8,
resultRelations = 0x225e348, nonleafResultRelations = 0x0, rootResultRelations = 0x0, subplans = 0x0,
rewindPlanIDs = 0x0, rowMarks = 0x0, relationOids = 0x225e2f8, invalItems = 0x0,
paramExecTypes = 0x21c4320, utilityStmt = 0x0, stmt_location = 0, stmt_len = 58}
#檢視planTree(執行計劃樹)
(gdb) p *((PlannedStmt *)(plantree_list->head->data.ptr_value))->planTree
$23 = {type = T_ModifyTable, startup_cost = 0, total_cost = 0.01, plan_rows = 1, plan_width = 298,
parallel_aware = false, parallel_safe = false, plan_node_id = 0, targetlist = 0x0, qual = 0x0,
lefttree = 0x0, righttree = 0x0, initPlan = 0x0, extParam = 0x0, allParam = 0x0}
...
#繼續執行,進入PortalRunMulti
(gdb) c
Continuing.
Breakpoint 3, PortalRunMulti (portal=0x2202490, isTopLevel=true, setHoldSnapshot=false, dest=0x225e4d8,
altdest=0x225e4d8, completionTag=0x7ffd6452f100 "") at pquery.c:1210
1210 bool active_snapshot_set = false;
#portal引數,其中stmts是已生成的PlannedStmt
(gdb) p *portal
$25 = {name = 0x2205e98 "", prepStmtName = 0x0, portalContext = 0x2252460, resowner = 0x21cdd10,
cleanup = 0x62f15c <PortalCleanup>, createSubid = 1, activeSubid = 1,
sourceText = 0x219cef0 "insert into t_insert values(25,'insert','insert','insert');",
commandTag = 0xb50908 "INSERT", stmts = 0x225e4a8, cplan = 0x0, portalParams = 0x0, queryEnv = 0x0,
strategy = PORTAL_MULTI_QUERY, cursorOptions = 4, run_once = true, status = PORTAL_ACTIVE,
portalPinned = false, autoHeld = false, queryDesc = 0x0, tupDesc = 0x0, formats = 0x0, holdStore = 0x0,
holdContext = 0x0, holdSnapshot = 0x0, atStart = true, atEnd = true, portalPos = 0,
creation_time = 587211499048183, visible = false}
(gdb) p *(portal->stmts)
$26 = {type = T_List, length = 1, head = 0x225e488, tail = 0x225e488}
(gdb) p *(PlannedStmt *)(portal->stmts->head.data->ptr_value)
$27 = {type = T_PlannedStmt, commandType = CMD_INSERT, queryId = 0, hasReturning = false,
hasModifyingCTE = false, canSetTag = true, transientPlan = false, dependsOnRole = false,
parallelModeNeeded = false, jitFlags = 0, planTree = 0x225dfe8, rtable = 0x225e2a8,
resultRelations = 0x225e348, nonleafResultRelations = 0x0, rootResultRelations = 0x0, subplans = 0x0,
rewindPlanIDs = 0x0, rowMarks = 0x0, relationOids = 0x225e2f8, invalItems = 0x0,
paramExecTypes = 0x21c4320, utilityStmt = 0x0, stmt_location = 0, stmt_len = 58}
#進入ProcessQuery
(gdb) c
Continuing.
Breakpoint 4, ProcessQuery (plan=0x225e378,
sourceText=0x219cef0 "insert into t_insert values(26,'insert','insert','insert');", params=0x0,
queryEnv=0x0, dest=0x225e4d8, completionTag=0x7ffd6452f100 "") at pquery.c:149
149 queryDesc = CreateQueryDesc(plan, sourceText,
#輸入引數,plan=PlannedStmt變數
(gdb) p *plan
$29 = {type = T_PlannedStmt, commandType = CMD_INSERT, queryId = 0, hasReturning = false,
hasModifyingCTE = false, canSetTag = true, transientPlan = false, dependsOnRole = false,
parallelModeNeeded = false, jitFlags = 0, planTree = 0x225dfe8, rtable = 0x225e2a8,
resultRelations = 0x225e348, nonleafResultRelations = 0x0, rootResultRelations = 0x0, subplans = 0x0,
rewindPlanIDs = 0x0, rowMarks = 0x0, relationOids = 0x225e2f8, invalItems = 0x0,
paramExecTypes = 0x21c4320, utilityStmt = 0x0, stmt_location = 0, stmt_len = 58}
#QueryDesc查詢描述符結構體,plannedstmt為先前生成的PlannedStmt
(gdb) p *queryDesc
$30 = {operation = CMD_INSERT, plannedstmt = 0x225e378,
sourceText = 0x219cef0 "insert into t_insert values(26,'insert','insert','insert');",
snapshot = 0x21c0920, crosscheck_snapshot = 0x0, dest = 0x225e4d8, params = 0x0, queryEnv = 0x0,
instrument_options = 0, tupDesc = 0x0, estate = 0x0, planstate = 0x0, already_executed = false,
totaltime = 0x0}
#進入standard_ExecutorRun,queryDesc為查詢描述符
(gdb) c
Continuing.
Breakpoint 5, standard_ExecutorRun (queryDesc=0x2252570, direction=ForwardScanDirection, count=0,
execute_once=true) at execMain.c:322
322 estate = queryDesc->estate;
#ProcessQuery函式構建了PlanState/EState(ExecutorState)/tupDesc,為Execute作準備
(gdb) p *queryDesc
$31 = {operation = CMD_INSERT, plannedstmt = 0x225e378,
sourceText = 0x219cef0 "insert into t_insert values(26,'insert','insert','insert');",
snapshot = 0x21c0920, crosscheck_snapshot = 0x0, dest = 0x225e4d8, params = 0x0, queryEnv = 0x0,
instrument_options = 0, tupDesc = 0x2254d50, estate = 0x2253c80, planstate = 0x2253fd0,
already_executed = false, totaltime = 0x0}
(gdb) p *(queryDesc->estate)
$32 = {type = T_EState, es_direction = ForwardScanDirection, es_snapshot = 0x21c0920,
es_crosscheck_snapshot = 0x0, es_range_table = 0x225e2a8, es_plannedstmt = 0x225e378,
es_sourceText = 0x219cef0 "insert into t_insert values(26,'insert','insert','insert');",
es_junkFilter = 0x0, es_output_cid = 0, es_result_relations = 0x2253ec0, es_num_result_relations = 1,
es_result_relation_info = 0x0, es_root_result_relations = 0x0, es_num_root_result_relations = 0,
es_tuple_routing_result_relations = 0x0, es_trig_target_relations = 0x0, es_trig_tuple_slot = 0x2254e30,
es_trig_oldtup_slot = 0x0, es_trig_newtup_slot = 0x0, es_param_list_info = 0x0,
es_param_exec_vals = 0x2253e90, es_queryEnv = 0x0, es_query_cxt = 0x2253b70, es_tupleTable = 0x2254880,
es_rowMarks = 0x0, es_processed = 0, es_lastoid = 0, es_top_eflags = 0, es_instrument = 0,
es_finished = false, es_exprcontexts = 0x2254230, es_subplanstates = 0x0, es_auxmodifytables = 0x0,
es_per_tuple_exprcontext = 0x0, es_epqTuple = 0x0, es_epqTupleSet = 0x0, es_epqScanDone = 0x0,
es_use_parallel_mode = false, es_query_dsa = 0x0, es_jit_flags = 0, es_jit = 0x0}
(gdb) p *(queryDesc->planstate)
$33 = {type = T_ModifyTableState, plan = 0x225dfe8, state = 0x2253c80,
ExecProcNode = 0x69a78b <ExecProcNodeFirst>, ExecProcNodeReal = 0x6c2485 <ExecModifyTable>,
instrument = 0x0, worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0,
subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2254d80, ps_ExprContext = 0x0, ps_ProjInfo = 0x0,
scandesc = 0x0}
(gdb) p *(queryDesc->tupDesc)
$34 = {natts = 0, tdtypeid = 2249, tdtypmod = -1, tdhasoid = false, tdrefcount = -1, constr = 0x0,
attrs = 0x2254d70}
#進入ExecutePlan
(gdb) c
Continuing.
Breakpoint 6, ExecutePlan (estate=0x2253c80, planstate=0x2253fd0, use_parallel_mode=false,
operation=CMD_INSERT, sendTuples=false, numberTuples=0, direction=ForwardScanDirection, dest=0x225e4d8,
execute_once=true) at execMain.c:1697
1697 current_tuple_count = 0;
#輸入引數,EState/PlanState,準備執行SQL
(gdb) p *estate
$35 = {type = T_EState, es_direction = ForwardScanDirection, es_snapshot = 0x21c0920,
es_crosscheck_snapshot = 0x0, es_range_table = 0x225e2a8, es_plannedstmt = 0x225e378,
es_sourceText = 0x219cef0 "insert into t_insert values(26,'insert','insert','insert');",
es_junkFilter = 0x0, es_output_cid = 0, es_result_relations = 0x2253ec0, es_num_result_relations = 1,
es_result_relation_info = 0x0, es_root_result_relations = 0x0, es_num_root_result_relations = 0,
es_tuple_routing_result_relations = 0x0, es_trig_target_relations = 0x0, es_trig_tuple_slot = 0x2254e30,
es_trig_oldtup_slot = 0x0, es_trig_newtup_slot = 0x0, es_param_list_info = 0x0,
es_param_exec_vals = 0x2253e90, es_queryEnv = 0x0, es_query_cxt = 0x2253b70, es_tupleTable = 0x2254880,
es_rowMarks = 0x0, es_processed = 0, es_lastoid = 0, es_top_eflags = 0, es_instrument = 0,
es_finished = false, es_exprcontexts = 0x2254230, es_subplanstates = 0x0, es_auxmodifytables = 0x0,
es_per_tuple_exprcontext = 0x0, es_epqTuple = 0x0, es_epqTupleSet = 0x0, es_epqScanDone = 0x0,
es_use_parallel_mode = false, es_query_dsa = 0x0, es_jit_flags = 0, es_jit = 0x0}
(gdb) p *planstate
$36 = {type = T_ModifyTableState, plan = 0x225dfe8, state = 0x2253c80,
ExecProcNode = 0x69a78b <ExecProcNodeFirst>, ExecProcNodeReal = 0x6c2485 <ExecModifyTable>,
instrument = 0x0, worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0,
subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2254d80, ps_ExprContext = 0x0, ps_ProjInfo = 0x0,
scandesc = 0x0}
#在ExecutePlan函式中執行ExecProcNode,直至ExecProcNode函式返回的TupleTableSlot為空才退出迴圈
1726 slot = ExecProcNode(planstate);
(gdb)
#進入ExecProcNode
#執行PlanState的ExecProcNode函式,即ExecProcNodeFirst
Breakpoint 7, ExecProcNode (node=0x2253fd0) at ../../../src/include/executor/executor.h:234
234 if (node->chgParam != NULL) /* something changed? */
(gdb)
237 return node->ExecProcNode(node);
(gdb)
#進入ExecProcNodeFirst
Breakpoint 8, ExecProcNodeFirst (node=0x2253fd0) at execProcnode.c:433
433 check_stack_depth();
#執行node的ExecProcNode函式,即ExecModifyTable(注:PlanState中的ExecProcNodeReal)
(gdb) p *node
$37 = {type = T_ModifyTableState, plan = 0x225dfe8, state = 0x2253c80,
ExecProcNode = 0x6c2485 <ExecModifyTable>, ExecProcNodeReal = 0x6c2485 <ExecModifyTable>,
instrument = 0x0, worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0,
subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2254d80, ps_ExprContext = 0x0, ps_ProjInfo = 0x0,
scandesc = 0x0}
...
#在for迴圈中執行subplanstate的ExecProcNode,同樣的,如果返回的Slot為NULL則退出
(gdb) p subplanstate
$38 = (PlanState *) 0x22543a0
(gdb) p *subplanstate #node->mt_plans[node->mt_whichplan];//執行計劃的State
$39 = {type = T_ResultState, plan = 0x21c44e0, state = 0x2253c80,
ExecProcNode = 0x69a78b <ExecProcNodeFirst>, ExecProcNodeReal = 0x6c5094 <ExecResult>, instrument = 0x0,
worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0,
chgParam = 0x0, ps_ResultTupleSlot = 0x2254750, ps_ExprContext = 0x22544b0, ps_ProjInfo = 0x22548b0,
scandesc = 0x0}
(gdb) p *node
$40 = {ps = {type = T_ModifyTableState, plan = 0x225dfe8, state = 0x2253c80,
ExecProcNode = 0x6c2485 <ExecModifyTable>, ExecProcNodeReal = 0x6c2485 <ExecModifyTable>,
instrument = 0x0, worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0,
subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2254d80, ps_ExprContext = 0x0, ps_ProjInfo = 0x0,
scandesc = 0x0}, operation = CMD_INSERT, canSetTag = true, mt_done = false, mt_plans = 0x22541e0,
mt_nplans = 1, mt_whichplan = 0, resultRelInfo = 0x2253ec0, rootResultRelInfo = 0x0,
mt_arowmarks = 0x22541f8, mt_epqstate = {estate = 0x0, planstate = 0x0, origslot = 0x0, plan = 0x21c44e0,
arowMarks = 0x0, epqParam = 0}, fireBSTriggers = false, mt_existing = 0x0, mt_excludedtlist = 0x0,
mt_conflproj = 0x0, mt_partition_tuple_routing = 0x0, mt_transition_capture = 0x0,
mt_oc_transition_capture = 0x0, mt_per_subplan_tupconv_maps = 0x0}
(gdb) n
1974 saved_resultRelInfo = estate->es_result_relation_info;
(gdb)
1976 estate->es_result_relation_info = resultRelInfo;
(gdb)
1990 ResetPerTupleExprContext(estate);
(gdb)
1992 planSlot = ExecProcNode(subplanstate);
(gdb)
Breakpoint 7, ExecProcNode (node=0x22543a0) at ../../../src/include/executor/executor.h:234
234 if (node->chgParam != NULL) /* something changed? */
(gdb)
237 return node->ExecProcNode(node);
(gdb)
#再次進入ExecProcNodeFirst,Node變為T_ResultState
Breakpoint 8, ExecProcNodeFirst (node=0x22543a0) at execProcnode.c:433
433 check_stack_depth();
(gdb)
440 if (node->instrument)
(gdb)
443 node->ExecProcNode = node->ExecProcNodeReal;
(gdb)
445 return node->ExecProcNode(node);
(gdb) p *node
$41 = {type = T_ResultState, plan = 0x21c44e0, state = 0x2253c80, ExecProcNode = 0x6c5094 <ExecResult>,
ExecProcNodeReal = 0x6c5094 <ExecResult>, instrument = 0x0, worker_instrument = 0x0, qual = 0x0,
lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0,
ps_ResultTupleSlot = 0x2254750, ps_ExprContext = 0x22544b0, ps_ProjInfo = 0x22548b0, scandesc = 0x0}
(gdb)
#進入ExecInsert
2126 slot = ExecInsert(node, slot, planSlot,
(gdb)
Breakpoint 10, ExecInsert (mtstate=0x2253fd0, slot=0x2254750, planSlot=0x2254750, estate=0x2253c80,
canSetTag=true) at nodeModifyTable.c:273
273 List *recheckIndexes = NIL;
#呼叫heap_insert等函式插入資料
(gdb) c
Continuing.
Breakpoint 11, heap_insert (relation=0x7f1a5655b378, tup=0x2254ee0, cid=0, options=0, bistate=0x0)
at heapam.c:2444
2444 TransactionId xid = GetCurrentTransactionId();
(gdb) c
Continuing.
Breakpoint 12, RelationPutHeapTuple (relation=0x7f1a5655b378, buffer=95, tuple=0x2254ee0, token=false)
at hio.c:51
51 pageHeader = BufferGetPage(buffer);
(gdb) c
Continuing.
Breakpoint 13, PageAddItemExtended (page=0x7f1a3e6a3300 "\001", item=0x2254ef8 "g\234\030", size=49,
offsetNumber=0, flags=2) at bufpage.c:196
196 PageHeader phdr = (PageHeader) page;
(gdb) finish
Run till exit from #0 PageAddItemExtended (page=0x7f1a3e6a3300 "\001", item=0x2254ef8 "g\234\030", size=49,
offsetNumber=0, flags=2) at bufpage.c:196
0x00000000004cf4f9 in RelationPutHeapTuple (relation=0x7f1a5655b378, buffer=95, tuple=0x2254ee0, token=false)
at hio.c:53
53 offnum = PageAddItem(pageHeader, (Item) tuple->t_data,
Value returned is $42 = 41
...
#再次執行ExecProcNode(實質為ExecResult),返回NULL,退出迴圈,結束
(gdb) c
Continuing.
Breakpoint 7, ExecProcNode (node=0x22543a0) at ../../../src/include/executor/executor.h:234
234 if (node->chgParam != NULL) /* something changed? */
(gdb) p *node
$48 = {type = T_ResultState, plan = 0x21c44e0, state = 0x2253c80, ExecProcNode = 0x6c5094 <ExecResult>,
ExecProcNodeReal = 0x6c5094 <ExecResult>, instrument = 0x0, worker_instrument = 0x0, qual = 0x0,
lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0,
ps_ResultTupleSlot = 0x2254750, ps_ExprContext = 0x22544b0, ps_ProjInfo = 0x22548b0, scandesc = 0x0}
(gdb) c
Continuing.
三、小結
1.執行過程:使用gdb跟蹤INSERT語句執行的全過程;
2.資料結構:如PlannedStmt/PlanState/EState等
3."多型":ExecProcNode函式
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/6906/viewspace-2374901/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- PostgreSQL的insert語句執行過程分析SQL
- PostgreSQL 原始碼解讀(21)- 查詢語句#6(PlannedStmt詳解-跟蹤分析)SQL原始碼
- MySQL全文索引原始碼剖析之Insert語句執行過程MySql索引原始碼
- PostgreSQL 原始碼解讀(14)- Insert語句(如何構造PlannedStmt)SQL原始碼
- [zebra原始碼]分片語句ShardPreparedStatement執行過程原始碼
- Oracle執行語句跟蹤 使用sql trace實現語句追蹤OracleSQL
- TiDB 原始碼閱讀系列文章(十六)INSERT 語句詳解TiDB原始碼
- Mybatis原始碼分析(五)探究SQL語句的執行過程MyBatis原始碼SQL
- 深入解讀MySQL InnoDB儲存引擎Update語句執行過程MySql儲存引擎
- mysql執行sql語句過程MySql
- PostgreSQL 原始碼解讀(65)- 查詢語句#50(make_one_rel函式#15-...SQL原始碼函式
- PostgreSQL 原始碼解讀(19)- 查詢語句#4(ParseTree詳解)SQL原始碼
- PostgreSQL 原始碼解讀(18)- 查詢語句#3(SQL Parse)SQL原始碼
- PostgreSQL 原始碼解讀(131)- MVCC#15(vacuum過程-lazy_vacuum_heap函式)SQL原始碼MVCC#函式
- PostgreSQL 原始碼解讀(126)- MVCC#10(vacuum過程)SQL原始碼MVCC#
- PostgreSQL 原始碼解讀(83)- 查詢語句#68(PortalStart函式)SQL原始碼函式
- PostgreSQL 原始碼解讀(75)- 查詢語句#60(Review - standard_...SQL原始碼View
- PostgreSQL 原始碼解讀(74)- 查詢語句#59(Review - subquery_...SQL原始碼View
- PostgreSQL 原始碼解讀(42)- 查詢語句#27(等價類)SQL原始碼
- MySQL探祕(二):SQL語句執行過程詳解MySql
- Java原始碼跟蹤閱讀技巧Java原始碼
- PostgreSQL 原始碼解讀(4)- 插入資料#3(heap_insert)SQL原始碼
- PostgreSQL 原始碼解讀(82)- 查詢語句#67(PortalXXX系列函式)SQL原始碼函式
- PostgreSQL 原始碼解讀(81)- 查詢語句#66(Review - exec_simp...SQL原始碼View
- PostgreSQL 原始碼解讀(89)- 查詢語句#74(SeqNext函式#2)SQL原始碼函式
- PostgreSQL 原始碼解讀(90)- 查詢語句#75(ExecHashJoin函式#1)SQL原始碼函式
- PostgreSQL 原始碼解讀(91)- 查詢語句#76(ExecHashJoin函式#2)SQL原始碼函式
- PostgreSQL 原始碼解讀(88)- 查詢語句#73(SeqNext函式#1)SQL原始碼函式
- PostgreSQL 原始碼解讀(87)- 查詢語句#72(PortalRunSelect->E...SQL原始碼
- PostgreSQL 原始碼解讀(84)- 查詢語句#69(PortalStart->InitP...SQL原始碼
- PostgreSQL 原始碼解讀(85)- 查詢語句#70(PortalRun->InitPla...SQL原始碼
- PostgreSQL 原始碼解讀(86)- 查詢語句#71(PortalRun->PortalR...SQL原始碼
- PostgreSQL 原始碼解讀(93)- 查詢語句#77(ExecHashJoin函式#3)SQL原始碼函式
- PostgreSQL 原始碼解讀(50)- 查詢語句#35(Optimizer Review#1)SQL原始碼View
- PostgreSQL 原始碼解讀(51)- 查詢語句#36(Optimizer Review#2)SQL原始碼View
- PostgreSQL 原始碼解讀(24)- 查詢語句#9(查詢重寫)SQL原始碼
- 一條sql語句的執行過程SQL
- PostgreSQL 原始碼解讀(30)- 查詢語句#15(查詢優化-扁平化處理UNION ALL)SQL原始碼優化