(gdb) b tuplesort.c:3137 if srcTape == 2 && state->maxTapes == 4
上述步骤完成之后,我们在 psql 中执行下面的语句:
1
ALTERTABLE pgbench_accounts ADDPRIMARY KEY (aid);
断点触发之后,我们可以再新增一个断点 b BufFileLogicalToPhysicalPos,随后在 GDB 中执行 continue,此时的堆栈信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#0 BufFileLogicalToPhysicalPos (pos=2142765056) at /home/japin/Codes/pgtde/build/../src/include/storage/buffile.h:100 #1 0x00005606b8dfa46e in BufFileSeek (file=0x5606ba03e808, fileno=2, offset=0, whence=0) at /home/japin/Codes/pgtde/build/../src/backend/storage/file/buffile.c:961 #2 0x00005606b8dfaacf in BufFileSeekBlock (file=0x5606ba03e808, blknum=261568) at /home/japin/Codes/pgtde/build/../src/backend/storage/file/buffile.c:1176 #3 0x00005606b9017eca in ltsReadBlock (lts=0x5606ba0449c0, blocknum=261568, buffer=0x7fe2b0418048) at /home/japin/Codes/pgtde/build/../src/backend/utils/sort/logtape.c:288 #4 0x00005606b901800b in ltsReadFillBuffer (lts=0x5606ba0449c0, lt=0x5606ba044c00) at /home/japin/Codes/pgtde/build/../src/backend/utils/sort/logtape.c:324 #5 0x00005606b9018993 in ltsInitReadBuffer (lts=0x5606ba0449c0, lt=0x5606ba044c00) at /home/japin/Codes/pgtde/build/../src/backend/utils/sort/logtape.c:661 #6 0x00005606b9019157 in LogicalTapeRead (lts=0x5606ba0449c0, tapenum=2, ptr=0x7fff52ff05b4, size=4) at /home/japin/Codes/pgtde/build/../src/backend/utils/sort/logtape.c:989 #7 0x00005606b9021ebc in getlen (state=0x5606ba0286b8, tapenum=2, eofOK=true) at /home/japin/Codes/pgtde/build/../src/backend/utils/sort/tuplesort.c:3706 #8 0x00005606b9020fe9 in mergereadnext (state=0x5606ba0286b8, srcTape=2, stup=0x7fff52ff0630) at /home/japin/Codes/pgtde/build/../src/backend/utils/sort/tuplesort.c:3159 #9 0x00005606b9020f58 in beginmerge (state=0x5606ba0286b8) at /home/japin/Codes/pgtde/build/../src/backend/utils/sort/tuplesort.c:3137
last_seg_bytes = pos % BYTES_PER_SEGMENT_LOGICAL; if (last_seg_bytes > 0) { off_t full_blocks; int last_block_usage; int useful_per_block = BLCKSZ - SizeOfBufFilePageHeader;
full_blocks = last_seg_bytes / useful_per_block; result += full_blocks * BLCKSZ;
last_block_usage = last_seg_bytes % useful_per_block; if (last_block_usage > 0) result += last_block_usage; }
/* * Even if we're at block boundary, add the header size so that we end * up at usable position. * * 再加上 18 字节的头部长度,结果为 -2147483630 */ result += SizeOfBufFilePageHeader;
int plan_create_index_workers(Oid tableOid, Oid indexOid) { [...]
/* * If parallel_workers storage parameter is set for the table, accept that * as the number of parallel worker processes to launch (though still cap * at max_parallel_maintenance_workers). Note that we deliberately do not * consider any other factor when parallel_workers is set. (e.g., memory * use by workers.) */ if (rel->rel_parallel_workers != -1) { parallel_workers = Min(rel->rel_parallel_workers, max_parallel_maintenance_workers); goto done; }
[...]
/* * Estimate heap relation size ourselves, since rel->pages cannot be * trusted (heap RTE was marked as inheritance parent) */ estimate_rel_size(heap, NULL, &heap_blocks, &reltuples, &allvisfrac);
/* * Determine number of workers to scan the heap relation using generic * model */ parallel_workers = compute_parallel_worker(rel, heap_blocks, -1, max_parallel_maintenance_workers);
/* * Cap workers based on available maintenance_work_mem as needed. * * Note that each tuplesort participant receives an even share of the * total maintenance_work_mem budget. Aim to leave participants * (including the leader as a participant) with no less than 32MB of * memory. This leaves cases where maintenance_work_mem is set to 64MB * immediately past the threshold of being capable of launching a single * parallel worker to sort. */ while (parallel_workers > 0 && maintenance_work_mem / (parallel_workers + 1) < 32768L) parallel_workers--;