バッファ管理。タプルのロックの開放

トランザクションが終了すれば実質のロックは開放されるが、ページ上のタプルに対しロック時にオンにされたビットフラグはトランザクションのコミットやロールバックではオフにされない。
ロックが必要な処理(heap_lock_tuple(), heap_update(), heap_delete())が行われるたびにそのタプルの可視性チェックでフラグをオフにしているみたい。

SQL、チェックポイント、pg_filedumpを実行しながらタプルのinfomaskのフラグがどうかわるか見てみた。上段がpsqlで実行したSQL。下段がpg_filedumpを実行して確認したタプルの状況。

1. insert
crate table hoge (a int);
insert into hoge values (1);
checkpoint;
 Item   1 -- Length:   28  Offset: 8164 (0x1fe4)  Flags: NORMAL
  XMIN: 626  XMAX: 0  CID|XVAC: 0
  Block Id: 0  linp Index: 1   Attributes: 1   Size: 24
  infomask: 0x0800 (XMAX_INVALID)
2. select 〜 for share
select * from hoge for share;
checkpoint;
 Item   1 -- Length:   28  Offset: 8164 (0x1fe4)  Flags: NORMAL
  XMIN: 626  XMAX: 627  CID|XVAC: 0
  Block Id: 0  linp Index: 1   Attributes: 1   Size: 24
  infomask: 0x0180 (XMAX_SHARED_LOCK|XMIN_COMMITTED)
3. delete
delete from hoge;
checkpoint;
 Item   1 -- Length:   28  Offset: 8164 (0x1fe4)  Flags: NORMAL
  XMIN: 626  XMAX: 628  CID|XVAC: 0
  Block Id: 0  linp Index: 1   Attributes: 1   Size: 24
  infomask: 0x0100 (XMIN_COMMITTED)
4. select (selectの結果は0件だけどまだページに残っているタプルのinfomaskは変更される)
select * from hoge;
checkpoint;
 Item   1 -- Length:   28  Offset: 8164 (0x1fe4)  Flags: NORMAL
  XMIN: 626  XMAX: 628  CID|XVAC:o 0
  Block Id: 0  linp Index: 1   Attributes: 1   Size: 24
  infomask: 0x0500 (XMIN_COMMITTED|XMAX_COMMITTED)

所感

  • select 〜 for share をするとXMAX_SHARED_LOCKがオンになる。トランザクションが終わってもオンのまま。
  • select 〜 for share するとXMAXに値が入る。UPDATEやDELETEでタプルが削除あつかいになるときだけ埋まると思っていたけどそうではなかった。なぜ埋める必要があるのだろう?どのトランザクションでロックされているか(トランザクションが実行中で待つべきかトランザクションが終了していて待つ必要がないか)知るためかな?
  • deleteするとXMAX_SHARED_LOCKはオフになる。

infomaskのフラグの状態遷移は難しい。まだぜんぜん把握できていない。