Scenario 15: Debugging Assistance¶
Developer debugging issues with code navigation and analysis.
Table of Contents¶
- Quick Start
- Call Path Tracing
- Trace Function Execution
- Reverse Trace (Callees)
- Error Path Analysis
- Find Error Handlers
- Exception Flow
- State Analysis
- Variable Tracking
- Debugging Workflows
- Quick Debug Checklist
- Example Questions
- Related Scenarios
Quick Start¶
# Select Debugging Scenario
/select 15
Call Path Tracing¶
Trace Function Execution¶
> Trace the call path to heap_insert
╭─────────────── Call Path ───────────────────────────────────╮
│ │
│ Target: heap_insert() │
│ Location: src/backend/access/heap/heapam.c:2156 │
│ │
│ Call Paths (top 3 by frequency): │
│ │
│ Path 1 (INSERT statement): │
│ exec_simple_query() │
│ └── PortalRun() │
│ └── ExecutorRun() │
│ └── ExecModifyTable() │
│ └── ExecInsert() │
│ └── table_tuple_insert() │
│ └── heap_insert() ← │
│ │
│ Path 2 (COPY command): │
│ DoCopy() │
│ └── CopyFrom() │
│ └── CopyMultiInsertBufferFlush() │
│ └── heap_insert() ← │
│ │
│ Path 3 (Trigger execution): │
│ ExecCallTriggerFunc() │
│ └── heap_insert() ← │
│ │
╰──────────────────────────────────────────────────────────────╯
Reverse Trace (Callees)¶
> What functions does heap_insert call?
╭─────────────── Callees ─────────────────────────────────────╮
│ │
│ heap_insert() calls: │
│ │
│ Memory/Buffer: │
│ RelationGetBufferForTuple() - Get target buffer │
│ BufferGetPage() - Get page from buffer │
│ PageAddItem() - Add item to page │
│ MarkBufferDirty() - Mark for write │
│ │
│ Transaction: │
│ GetCurrentTransactionId() - Get XID │
│ TransactionIdStore() - Store XID in tuple │
│ │
│ Locking: │
│ LockBuffer() - Lock buffer │
│ UnlockReleaseBuffer() - Unlock and release │
│ │
│ Logging: │
│ XLogInsert() - WAL logging │
│ log_heap_insert() - Heap-specific WAL │
│ │
│ Total direct callees: 23 │
│ │
╰──────────────────────────────────────────────────────────────╯
Error Path Analysis¶
Find Error Handlers¶
> What error handlers exist for heap operations?
╭─────────────── Error Handlers ──────────────────────────────╮
│ │
│ Error Handling in Heap Module: │
│ │
│ ereport(ERROR) locations: │
│ │
│ heap_insert(): │
│ Line 2178: "tuple too big" │
│ Line 2189: "no free space on page" │
│ │
│ heap_update(): │
│ Line 3456: "concurrent update detected" │
│ Line 3478: "tuple updated by different transaction" │
│ │
│ heap_delete(): │
│ Line 2890: "tuple already deleted" │
│ │
│ PG_TRY/PG_CATCH blocks: │
│ heap_vacuum_rel(): 2 exception handlers │
│ heap_prepare_insert(): 1 exception handler │
│ │
│ Total error paths: 15 │
│ │
╰──────────────────────────────────────────────────────────────╯
Exception Flow¶
> Trace what happens when heap_insert fails
╭─────────────── Exception Flow ──────────────────────────────╮
│ │
│ Exception: "tuple too big" in heap_insert() │
│ │
│ Exception Path: │
│ heap_insert() raises ERROR │
│ ↓ │
│ PG_CATCH in ExecModifyTable() │
│ ↓ (no specific handler, re-raise) │
│ PG_CATCH in ExecutorRun() │
│ ↓ (cleanup, re-raise) │
│ PG_CATCH in PortalRun() │
│ ↓ (abort transaction) │
│ PG_CATCH in PostgresMain() │
│ → Send error to client │
│ → Rollback transaction │
│ → Continue main loop │
│ │
│ Resources Cleaned Up: │
│ - Buffers released │
│ - Locks released │
│ - Memory contexts reset │
│ │
╰──────────────────────────────────────────────────────────────╯
State Analysis¶
Variable Tracking¶
> Track the state of 'tuple' variable through heap_insert
╭─────────────── Variable State ──────────────────────────────╮
│ │
│ Variable: tuple (HeapTuple) │
│ Function: heap_insert() │
│ │
│ State Transitions: │
│ │
│ Line 2160: [INPUT] Received from caller │
│ State: Initialized, no OID │
│ │
│ Line 2165: [MODIFIED] HeapTupleSetOid() │
│ State: OID assigned │
│ │
│ Line 2170: [MODIFIED] HeapTupleHeaderSetXmin() │
│ State: Xmin set to current XID │
│ │
│ Line 2178: [CHECKED] tuple size validation │
│ State: Validated or ERROR │
│ │
│ Line 2190: [MODIFIED] PageAddItem() │
│ State: Stored in buffer page │
│ │
│ Line 2210: [OUTPUT] Return to caller │
│ State: Fully inserted, WAL logged │
│ │
╰──────────────────────────────────────────────────────────────╯
Debugging Workflows¶
Quick Debug Checklist¶
> Generate debug checklist for heap_insert issues
╭─────────────── Debug Checklist ─────────────────────────────╮
│ │
│ Debugging heap_insert() Issues: │
│ │
│ 1. Check Input Validity │
│ □ Is relation valid and open? │
│ □ Is tuple properly formed? │
│ □ Is tuple size within limits? │
│ │
│ 2. Check Transaction State │
│ □ Is there an active transaction? │
│ □ Is the transaction ID valid? │
│ □ Check for transaction wraparound │
│ │
│ 3. Check Buffer State │
│ □ Is buffer properly locked? │
│ □ Is there free space on page? │
│ □ Is buffer dirty flag set? │
│ │
│ 4. Check WAL State │
│ □ Is WAL logging enabled? │
│ □ Is the WAL insert successful? │
│ □ Check WAL buffer space │
│ │
│ 5. Common Errors │
│ □ "tuple too big" → Check tuple size │
│ □ "no free space" → Check autovacuum │
│ □ "deadlock" → Check lock ordering │
│ │
╰──────────────────────────────────────────────────────────────╯
Example Questions¶
- “Trace the call path to [function]”
- “What functions does [function] call?”
- “Find error handlers in [module]”
- “What happens when [function] fails?”
- “Track variable [name] through [function]”
- “Generate debug checklist for [issue]”
Related Scenarios¶
- Onboarding - Understanding code structure
- Performance - Performance debugging
- Feature Development - Understanding call chains