PostgreSQL 源码解读(15)- Insert语句(执行过程跟踪)
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本文简单介绍了PG INSERT语句的执行全过程,包括使用gdb跟踪调试的全过程,重点的数据结构等。一、调用栈INSERT语句的函数调用栈:(gdb) bt#0 PageAddItemExtende
千家信息网最后更新 2026年11月02日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=# -- 获取pidtestdb=# 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 3294GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7Copyright (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) cContinuing.Breakpoint 2, exec_simple_query ( query_string=0x219cef0 "insert into t_insert values(25,'insert','insert','insert');") at postgres.c:893893 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) n1054 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) cContinuing.Breakpoint 3, PortalRunMulti (portal=0x2202490, isTopLevel=true, setHoldSnapshot=false, dest=0x225e4d8, altdest=0x225e4d8, completionTag=0x7ffd6452f100 "") at pquery.c:12101210 bool active_snapshot_set = false;#portal参数,其中stmts是已生成的PlannedStmt(gdb) p *portal$25 = {name = 0x2205e98 "", prepStmtName = 0x0, portalContext = 0x2252460, resowner = 0x21cdd10, cleanup = 0x62f15c , 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) cContinuing.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:149149 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) cContinuing.Breakpoint 5, standard_ExecutorRun (queryDesc=0x2252570, direction=ForwardScanDirection, count=0, execute_once=true) at execMain.c:322322 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 , ExecProcNodeReal = 0x6c2485 , 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) cContinuing.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:16971697 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 , ExecProcNodeReal = 0x6c2485 , 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函数,即ExecProcNodeFirstBreakpoint 7, ExecProcNode (node=0x2253fd0) at ../../../src/include/executor/executor.h:234234 if (node->chgParam != NULL) /* something changed? */(gdb) 237 return node->ExecProcNode(node);(gdb) #进入ExecProcNodeFirstBreakpoint 8, ExecProcNodeFirst (node=0x2253fd0) at execProcnode.c:433433 check_stack_depth();#执行node的ExecProcNode函数,即ExecModifyTable(注:PlanState中的ExecProcNodeReal)(gdb) p *node$37 = {type = T_ModifyTableState, plan = 0x225dfe8, state = 0x2253c80, ExecProcNode = 0x6c2485 , ExecProcNodeReal = 0x6c2485 , 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 , ExecProcNodeReal = 0x6c5094 , 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 , ExecProcNodeReal = 0x6c2485 , 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) n1974 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:234234 if (node->chgParam != NULL) /* something changed? */(gdb) 237 return node->ExecProcNode(node);(gdb) #再次进入ExecProcNodeFirst,Node变为T_ResultStateBreakpoint 8, ExecProcNodeFirst (node=0x22543a0) at execProcnode.c:433433 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 , ExecProcNodeReal = 0x6c5094 , 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) #进入ExecInsert2126 slot = ExecInsert(node, slot, planSlot,(gdb) Breakpoint 10, ExecInsert (mtstate=0x2253fd0, slot=0x2254750, planSlot=0x2254750, estate=0x2253c80, canSetTag=true) at nodeModifyTable.c:273273 List *recheckIndexes = NIL;#调用heap_insert等函数插入数据(gdb) cContinuing.Breakpoint 11, heap_insert (relation=0x7f1a5655b378, tup=0x2254ee0, cid=0, options=0, bistate=0x0) at heapam.c:24442444 TransactionId xid = GetCurrentTransactionId();(gdb) cContinuing.Breakpoint 12, RelationPutHeapTuple (relation=0x7f1a5655b378, buffer=95, tuple=0x2254ee0, token=false) at hio.c:5151 pageHeader = BufferGetPage(buffer);(gdb) cContinuing.Breakpoint 13, PageAddItemExtended (page=0x7f1a3e6a3300 "\001", item=0x2254ef8 "g\234\030", size=49, offsetNumber=0, flags=2) at bufpage.c:196196 PageHeader phdr = (PageHeader) page;(gdb) finishRun till exit from #0 PageAddItemExtended (page=0x7f1a3e6a3300 "\001", item=0x2254ef8 "g\234\030", size=49, offsetNumber=0, flags=2) at bufpage.c:1960x00000000004cf4f9 in RelationPutHeapTuple (relation=0x7f1a5655b378, buffer=95, tuple=0x2254ee0, token=false) at hio.c:5353 offnum = PageAddItem(pageHeader, (Item) tuple->t_data,Value returned is $42 = 41...#再次执行ExecProcNode(实质为ExecResult),返回NULL,退出循环,结束(gdb) cContinuing.Breakpoint 7, ExecProcNode (node=0x22543a0) at ../../../src/include/executor/executor.h:234234 if (node->chgParam != NULL) /* something changed? */(gdb) p *node$48 = {type = T_ResultState, plan = 0x21c44e0, state = 0x2253c80, ExecProcNode = 0x6c5094 , ExecProcNodeReal = 0x6c5094 , 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) cContinuing. 三、小结
1.执行过程:使用gdb跟踪INSERT语句执行的全过程;
2.数据结构:如PlannedStmt/PlanState/EState等
3."多态":ExecProcNode函数
函数
数据
生成
语句
跟踪
参数
元素
全过程
结构
循环
查询
输入
再次
实际
数据结构
类型
重点
准备
过程
多态
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
咖啡豆
重生之互联网科技帝国
互联网金融监管科技数据
深圳互联网科技公司
互联网金融 科技金融
云电互联网科技
四个字互联网科技公司取名
天速互联网络科技有限公司
互联网科技有哪些公司
浙江互联网科技研学营
岳阳华臻互联网科技有限公司
互联网公司黑科技创始人
互联网科技公司营业执照怎么办理
合肥互联网科技公司公章图片
互联网方面的科技前沿
上海京穆互联网科技有限公司
互联网科技手机排行榜
中国科技和美国互联网
互联网科技收购价值
互联网科技快速发展优美句子
为想互联网科技怎么样
互联网巨头科技公司
互联网金融 金融科技
互联网 卓越科技
天津摩尔互联网科技
中国互联网有什么科技含量
中科明德北京互联网科技
科技互联网经济论坛
互联网科技创新创业项目
山东蛋芒互联网科技有限公司