バッファ管理。タプルの追加

シンプルなINSERTを行ったときの呼び出しシーケンス。ページにタプルを追加するところまで。

(gdb) bt
#0  PageAddItem (page=0xb5835260 "", item=0x84e4d04 "J\002", size=28, offsetNumber=3, overwrite=0 '\0', is_heap=1 '\001') at bufpage.c:249
#1  0x080a2cf8 in RelationPutHeapTuple (relation=0xb561a2f8, buffer=101, tuple=0x84e4cf0) at hio.c:43
#2  0x0809dbb8 in heap_insert (relation=0xb561a2f8, tup=0x84e4cf0, cid=2, use_wal=1 '\001', use_fsm=1 '\001') at heapam.c:1841
#3  0x0818d787 in ExecInsert (slot=0x84e4960, tupleid=0x0, planSlot=0x84e4960, dest=0x84ad820, estate=0x84e4848) at execMain.c:1632
#4  0x0818d500 in ExecutePlan (estate=0x84e4848, planstate=0x84e4a20, operation=CMD_INSERT, numberTuples=0, direction=ForwardScanDirection, dest=0x84ad820) at execMain.c:1485
#5  0x0818b98c in ExecutorRun (queryDesc=0x84cbdb0, direction=ForwardScanDirection, count=0) at execMain.c:270
#6  0x0824ddce in ProcessQuery (plan=0x84ad7b0, params=0x0, dest=0x84ad820, completionTag=0xbfc4d8da "") at pquery.c:179
#7  0x0824f248 in PortalRunMulti (portal=0x84de3f8, isTopLevel=1 '\001', dest=0x84ad820, altdest=0x84ad820, completionTag=0xbfc4d8da "") at pquery.c:1242
#8  0x0824ea27 in PortalRun (portal=0x84de3f8, count=2147483647, isTopLevel=1 '\001', dest=0x84ad820, altdest=0x84ad820, completionTag=0xbfc4d8da "") at pquery.c:813
#9  0x0824939c in exec_simple_query (query_string=0x84ac870 "insert into ccc values(10);") at postgres.c:986
#10 0x0824d15f in PostgresMain (argc=4, argv=0x8454520, username=0x84544f8 "postgres") at postgres.c:3572
#11 0x08217982 in BackendRun (port=0x8467d18) at postmaster.c:3207
#12 0x08216f0a in BackendStartup (port=0x8467d18) at postmaster.c:2830
#13 0x08214928 in ServerLoop () at postmaster.c:1274
#14 0x08214335 in PostmasterMain (argc=1, argv=0x8451578) at postmaster.c:1029
#15 0x081b6707 in main (argc=1, argv=0x8451578) at main.c:188

heap_insert()

注目したい関数はheap_insert()。タプルを追加する処理を行う。
ページに追加する前に次のようにMVCCに必要な情報などを付け加えている。

tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
tup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK);
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
HeapTupleHeaderSetXmin(tup->t_data, xid);
HeapTupleHeaderSetCmin(tup->t_data, cid);
HeapTupleHeaderSetXmax(tup->t_data, 0);     /* for cleanliness */
tup->t_tableOid = RelationGetRelid(relation);

WALのログの作成も行っている。

以下は、heap_insert()から呼ばれる主な関数。

  • RelationGetBufferForTuple()
    • タプルを追加するためのバッファを取得する。
  • RelationPutHeapTuple()
    • 取得したバッファにタプルを追加する。
  • MarkBufferDirty()
    • バッファのフレーム(バッファ記述子)にダーティだとしるしをつける。
  • XLogInsert()
    • WALバッファにログを書き込む。
  • PageSetLSN()
    • ページにLSNをセットする。このLSNはXLogInsertの戻り値。
  • PageSetTLI()
    • ページにタイムラインIDをセットする。
  • CacheInvalidateHeapTuple()
    • キャッシュを無効にする。

宿題

  • タプル追加のためにバッファを取得するロジックはどうなっている?
  • ログの情報はどのようなもの?
  • LSNとは何か?その役割は?
  • タイムラインIDとは何か?
  • キャッシュを無効にすると際のロジックはどうなっている?