áá«áá²á·áááºáááºáá²á· ááá
á¹á
ááœá±ááᯠáá»áœááºáá±á¬áºááá¯á· á
ááºážá
á¬ážáá¬ážáá«áááºá
header ááá¯
áá»áœááºá¯ááºááá¯á·ááŒá±á¬áá²á·ááá·áºá¡ááá¯ááºážá á¡áááºážáá áºáá¯á á®ááẠáá±áá¬áá±á·á áºááœáẠáá¬ážááŸááºážáá»á¬ážá áœá¬ááᯠáá áºááŒáá¯ááºáááºáááºáž áááºááŸáááá¯ááºáááºá áá¬ážááŸááºážáá áºáá¯ááẠá¡ááŒá¬ážáá¬ážááŸááºážáá áºáá¯ááŸáá·áº áá áºáááºážáááºážááŒáá·áº ááœá²ááŒá¬ážáá±ááá«áááºá á€áááºááœááºáá»ááºá¡ááœááºá áá¬ážááŸááºážáá áºáá¯á á®ááœáẠá€áá¬ážááŸááºážá "á¡áá»áááº" ááᯠáá¯á¶ážááŒááºááá·áº á¡ááŸááºá¡áá¬ážááŸá áºáᯠ(xmin ááŸáá·áº xmax)á ááá¯ážáá¬ážáá»ááºáá»á¬ážááœáẠ- á¡áá»áááºááá¯ááºáá±á¬ááŒá±á¬áá·áºá ááá¯á·áá±á¬áº á¡áá°ážááá¯ážááŒáá·áºááá·áº áááºááŒááºááᯠá¡áá¯á¶ážááŒá¯áááºá ááŒá®ážáá±á¬á· áá®áá±á¬ááºáá¬á ááœá±ááœáŸá²áá²á·áá¶áá«ááºáá«á
(áá¯á¶ááŸááºá¡ááá¯ááºážá á¡ááŒá
áºááŸááºá ááá¯ááŸá¯ááºááœá±ážáááº- áá±á¬ááºáá¬á á¡ááá·áºá¡áááºááŸááá±á¬ áá
áºá
áœááºážáááºááŒá±á¬áá·áº ááœá±áá±ážááœá±áá°áá¶áá«ááºááẠá¡áá»áááºááŒáá·áºáááá¯ážááá¯ááºáá«á ááá¯á·áá±á¬áº á¡á±ážáá²ááœá¬ážáá±á¬á¡áá«ááœáẠá€á¡áá±ážá
áááºá¡áá»ááºá¡áááºáá»á¬ážááᯠáá»áœááºá¯ááºááá¯á·ááŒáá·áºááŸá¯áá«áááºá)
á¡áááºážáá
áºáá¯ááᯠáááºáá®ážáá±á¬á¡áá«á xmin á¡á¬áž INSERT á¡áááá·áºááᯠáá¯ááºááŒááºááá·áº ááœá±áá±ážááœá±áá°áá¶áá«ááºááá¯á· áááºááŸááºáá¬ážááŒá®áž xmax ááᯠááá¬á¡ááŒá
Ạáá¬ážáá²á·áááºá
á¡áááºážáá áºáá¯ááᯠáá»ááºááá¯ááºáá±á¬á¡áá«á áááºááŸááá¬ážááŸááºážá xmax áááºááá¯ážááᯠDELETE áá¯ááºáá±á¬ááºááá·áº ááœá±áá±ážááœá±áá° áá¶áá«ááºááŒáá·áº á¡ááŸááºá¡áá¬ážááŒá¯áá«áááºá
á¡áááºážáá áºáá¯ááᯠUPDATE á¡áááá·áºááŒáá·áº ááœááºážáá¶áá±á¬á¡áá«á áá¯ááºáá±á¬ááºáá»ááºááŸá áºáá¯ááᯠá¡ááŸááºááááºáá¯ááºáá±á¬ááºáááº- DELETE ááŸáá·áº INSERTá á¡áááºážá áááºááŸááá¬ážááŸááºážááẠxmax ááᯠUPDATE ááŒá¯áá¯ááºááá·áº ááœá±áá±ážááœá±áá° á¡áá±á¡ááœááºááŸáá·áº áá®áá»áŸá á±áááºá ááá¯á·áá±á¬áẠáá°áá®áá±á¬á á¬ááŒá±á¬ááºážá áá¬ážááŸááºážá¡áá áºááᯠáááºáá®ážááŒá®ážá áááºážá xmin áááºááá¯ážááẠááááºáá¬ážááŸááºážá xmax áááºááá¯ážááŸáá·áº ááá¯ááºááá¯ááºáá±áááºá
xmin ááŸáá·áº xmax á¡ááœááºáá»á¬ážááᯠá¡áááºážáá¬ážááŸááºážáá±á«ááºážá á®ážááœáẠááá·áºááœááºážáá¬ážáááºá á€á¡ááœááºáá»á¬ážá¡ááŒááºá áá±á«ááºážá á®ážááœáẠá¡ááŒá¬ážáá±á¬ á¥ááá¬áá»á¬ážáá«ááŸááááºá
- infomask ááẠá€áá¬ážááŸááºážá áá¯ááºááá¹áááá»á¬ážááᯠáááºááŸááºáá±ážááá·áº á¡ááœá²áá»á¬ážááŒá áºáááºá áá°ááá¯á·áá²á áá±á¬áºáá±á¬áºáá»á¬ážáááºá ááŒááºážááŒááºážáá»ááºáž á¡ááá á ááºážá á¬ážáá«áááºá
- ctid ááẠáá°áá®áá±á¬ááá¯ááºážá áá±á¬ááºáááºáá¬ážááŸááºážá¡áá áºááá¯á· ááá·áºááºáá áºáá¯ááŒá áºáááºá á¡áá áºáá¯á¶ážá áááºááŸááá¬ážááŸááºážáá áºáá¯á¡ááœááºá ctid ááẠá€áá¬ážááŸááºážááá¯ááºááá¯ááºááᯠáááºááœáŸááºážáááºá áá¶áá«ááºááœáẠáá¯á¶á ᶠ(xá y) ááŸáááŒá®áž x ááẠá á¬áá»ááºááŸá¬áá¶áá«ááºááŒá áºááŒá®áž y ááẠarray ááŸá á¡ááœáŸááºážáá¶áá«ááºááŒá áºáááºá
- null bitmap - null value (NULL) áá«áááºááá·áº áá±ážáá¬ážáá±á¬áá¬ážááŸááºážáá áºáá¯á ááá¯áá±á¬áºáá¶áá»á¬ážááᯠá¡ááŸááºá¡áá¬ážááŒá¯áá«á NULL ááẠáá¬áááºáá±áá¬á¡áá»áá¯ážá¡á á¬ážáááºááá¯ážáá»á¬ážáá²ááŸáá áºáá¯ááá¯ááºáá«á ááá¯á·ááŒá±á¬áá·áº attribute ááᯠáá®ážááŒá¬ážááááºážáááºážáá¬ážááá«áááºá
ááááºá¡áá±ááŒáá·áº header ááẠá¡ááœááºááŒá®ážáá¬ážááẠ- ááá¯ááºážáá¬ážááŸááºážáá áºáá¯á á®á¡ááœáẠá¡áááºážáá¯á¶áž 23 bytes ááŸáááŒá®áž á¡áá»á¬ážá¡á¬ážááŒáá·áº NULL bitmap ááŒá±á¬áá·áº ááá¯ááá»á¬ážááŒá¬ážáááºá ááá¬ážááẠ"áá»ááºážáááº" (ááá¯ááá¯áááºááŸá¬á áá±á¬áºáá¶á¡áááºážáááºáá«ááŸááááº) ááẠá¡áá¯á¶ážáááºáá±á¬á¡áá»ááºá¡áááºááẠááá¯áá°ááá¯ááºáááºá
ááá·áºááœááºáž
ááá·áºááœááºážááŒááºážááŸá¡á ááŒá¯á á¡ááá·áºáááá·áº á á¬ááŒá±á¬ááºážáá»á¬áž áá¯ááºáá±á¬ááºáá¯á¶ááᯠá¡áá®ážááẠáá±á·áá¬ááŒáá·áºááŒáá«á áá¯á·á
á ááºážáááºááŸá¯áá»á¬ážá¡ááœááºá áá±á¬áºáá¶ááŸá áºáá¯ááŸáá·áº áááºážááá¯á·áá²á០áá áºáá¯áá±á«áºááœáẠá¡ááœáŸááºážáá áºáá¯áá«áá±á¬ ááá¬ážá¡áá áºáá áºáá¯ááᯠáááºáá®ážááŒáá«á áá¯á·á
=> CREATE TABLE t(
id serial,
s text
);
=> CREATE INDEX ON t(s);
ááœá±áá±ážááœá±áá°áá áºáᯠá áááºááŒá®ážáá±á¬áẠá¡áááºážáá áºáááºáž ááá·áºááŒáá«á áá¯á·á
=> BEGIN;
=> INSERT INTO t(s) VALUES ('FOO');
á€áááºááŸá¬ áá»áœááºá¯ááºááá¯á·á áááºááŸáááœá±áá±ážááœá±áá°áá¶áá«ááºááŒá áºáááº-
=> SELECT txid_current();
txid_current
--------------
3664
(1 row)
á á¬áá»ááºááŸá¬áá²á· á¡ááŒá±á¬ááºážá¡áá¬ááœá±ááᯠááŒáá·áºáá¡á±á¬ááºá pageinspect extension á heap_page_items áá¯ááºáá±á¬ááºáá»ááºááẠááá·áºá¡á¬áž pointers áá»á¬ážááŸáá·áº row versions áá»á¬ážá¡ááŒá±á¬ááºáž á¡áá»ááºá¡áááºáá»á¬ážááᯠáááŸáá á±áá«áááºá
=> SELECT * FROM heap_page_items(get_raw_page('t',0)) gx
-[ RECORD 1 ]-------------------
lp | 1
lp_off | 8160
lp_flags | 1
lp_len | 32
t_xmin | 3664
t_xmax | 0
t_field3 | 0
t_ctid | (0,1)
t_infomask2 | 2
t_infomask | 2050
t_hoff | 24
t_bits |
t_oid |
t_data | x0100000009464f4f
PostgreSQL ááŸá á
áá¬ážáá¯á¶áž heap ááẠááá¬ážáá»á¬ážááᯠáááºááœáŸááºážááŒá±á¬ááºáž áááááŒá¯áá«á á€áááºááŸá¬ á¡ááŸáá¯ááºáá¯á¶áá°áá±á¬ á¡áá¯á¶ážá¡ááŸá¯ááºážá áá±á¬ááºáááºáá°ážáááºážáá±á¬ á¡áá¯á¶ážá¡ááŸá¯ááºážááŒá
áºáááºá
áá¯ááºáá±á¬ááºáá»ááºááẠáá±áá¬ááᯠáá¬ážáááºááááºáá±á¬ áá±á¬áºáááºááŒáá·áº âááŒá áºááá²á·ááá¯á·â ááŒáááºá áááºážááᯠááááŸáááá¯ááºááẠáá»áœááºá¯ááºááá¯á·ááẠá¡áá»ááºá¡áááºá áá áºá áááºáá áºááá¯ááºážááá¯áᬠáá»ááºáá¬ážáá²á·áᬠáááºážááᯠáá¯á¶áá±á¬áºááŒááºáž-
=> SELECT '(0,'||lp||')' AS ctid,
CASE lp_flags
WHEN 0 THEN 'unused'
WHEN 1 THEN 'normal'
WHEN 2 THEN 'redirect to '||lp_off
WHEN 3 THEN 'dead'
END AS state,
t_xmin as xmin,
t_xmax as xmax,
(t_infomask & 256) > 0 AS xmin_commited,
(t_infomask & 512) > 0 AS xmin_aborted,
(t_infomask & 1024) > 0 AS xmax_commited,
(t_infomask & 2048) > 0 AS xmax_aborted,
t_ctid
FROM heap_page_items(get_raw_page('t',0)) gx
-[ RECORD 1 ]-+-------
ctid | (0,1)
state | normal
xmin | 3664
xmax | 0
xmin_commited | f
xmin_aborted | f
xmax_commited | f
xmax_aborted | t
t_ctid | (0,1)
á€áááºááŸá¬ áá»áœááºá¯ááºááá¯á·ááŒá¯áá¯ááºáá²á·áááº-
- áááºážááᯠt_ctid ááŸáá·áºáá°á á±ááẠá¡ááœáŸááºážáá¶áá«ááºááá¯á· áá¯ááá áºáá¯ááá·áºáá²á·áááº- (á á¬áá»ááºááŸá¬áá¶áá«ááºá á¡ááœáŸááºážááááºážáá¶áá«ááº)á
- lp_flags ááœáŸááºááŒáá»ááºá á¡ááŒá±á¡áá±ááᯠáá¯á¶áá±á¬áºáá¬ážáááºá á€ááœááºáááºážááẠ"áá¬áááº" ááŒá áºááẠ- ááá¯ááá¯áááºááŸá¬ pointer ááẠstring ááá¬ážááŸááºážááᯠá¡ááŸááºááááºáááºááœáŸááºážáááºá áááŒá¬ážá¡áááá¹áá«ááºááœá±ááᯠáá±á¬ááºááŸááŒáá·áºáá«áááºá
- á¡áá»ááºá¡áááºá¡á¬ážáá¯á¶ážááœáẠá¡ááœá²ááŸá áºááœá²ááá¯áᬠááá¯á¡áá»áááºá¡áá áá±á¬áºáá¯ááºááá¯ááºáá²á·áááºá xmin_committed ááŸáá·áº xmin_aborted bits áá»á¬ážááẠááœá±áá±ážááœá±áá°áá¶áá«áẠxmin ááᯠáá»á°ážááœááºááŒááºážááŸááááŸá áá±á¬áºááŒááẠ(áá»ááºááááºážáá¬ážáááº)á á¡áá¬ážáá° bit ááŸá áºáá¯ááẠááœá±áá±ážááœá±áá°áá¶áá«áẠxmax ááᯠáááºááœáŸááºážáááºá
áá«ááá¯á· áá¬ááá¯ááŒááºáá²á á¡áááºážáá áºáá¯ááᯠáááºááá·áºááœááºážáá±á¬á¡áá«á á¡ááœáŸááºážááááºáž 1 ááẠá¡áááºážá ááááá¯á¶ážááŸáá·áº áá áºáá¯áááºážáá±á¬áá¬ážááŸááºážááᯠááœáŸááºááŒááŒá®áž ááá¬ážá á¬áá»ááºááŸá¬ááœáẠáá±á«áºáá¬áááá·áºáááºá
string áá¬ážááŸááºážááœááºá xmin á¡ááœááºááœáẠáááºááŸá ááœá±áá±ážááœá±áá°áá¶áá«ááºááŒáá·áº ááŒáá·áºáá¬ážáááºá ááœá±áá±ážááœá±áá°ááẠá¡áááºáááºáá±áá²ááŒá áºáá±á¬ááŒá±á¬áá·áº xmin_committed ááŸáá·áº xmin_aborted bits ááŸá áºáá¯áá¯á¶ážááᯠáááºááŸááºááá¬ážáá«á
á¡áááºážáá¬ážááŸááºáž ctid á¡ááœááºááẠáá°áá®áá±á¬á¡áááºážááᯠáááºááœáŸááºážáááºá ááá¯ááá¯áááºááŸá¬ áá¬ážááŸááºážá¡áá ẠáááŸááá«á
xmax á¡ááœááºááœáẠá€á¡áááºážáá€áá¬ážááŸááºážááᯠááá»ááºááá±ážáá² áááºááŸáááŒá áºáá±áá±á¬ááŒá±á¬áá·áº dummy áá¶áá«áẠ0 ááŸáá·áº ááŒáá·áºáá±áá«áááºá xmax_aborted bit ááá¯áááºááŸááºáá¬ážáá±á¬ááŒá±á¬áá·áº ááœá±áá±ážááœá±áá°áá»á¬ážááẠá€áá¶áá«ááºááá¯á¡á¬áá¯á¶á áá¯ááºáááºááá¯ááºáá«á
ááœá±áá±ážááœá±áá°áá¶áá«ááºáá»á¬ážááá¯á· á¡áá»ááºá¡áááºáá áºáá»á¬ážááá·áºááŒááºážááŒáá·áº áááºááá¯ááºá áœááºážáááºááᯠááŒáŸáá·áºáááºááẠáá±á¬ááºáááºááŒá±ááŸááºážáá áºáá¯ááŸááºážááŒáá«á áá¯á·á áá»áœááºá¯ááºááá¯á·ááẠáá±á¬ááºážááá¯áá»ááºááᯠáá áºááŒáááºáááºááá¯á ááá¯á¡ááºáá±á¬ááŒá±á¬áá·áº áá¯ááºáá±á¬ááºáá»ááºáá áºáá¯ááᯠáááºáá®ážááŒáá«á áá¯á·á
=> CREATE FUNCTION heap_page(relname text, pageno integer)
RETURNS TABLE(ctid tid, state text, xmin text, xmax text, t_ctid tid)
AS $$
SELECT (pageno,lp)::text::tid AS ctid,
CASE lp_flags
WHEN 0 THEN 'unused'
WHEN 1 THEN 'normal'
WHEN 2 THEN 'redirect to '||lp_off
WHEN 3 THEN 'dead'
END AS state,
t_xmin || CASE
WHEN (t_infomask & 256) > 0 THEN ' (c)'
WHEN (t_infomask & 512) > 0 THEN ' (a)'
ELSE ''
END AS xmin,
t_xmax || CASE
WHEN (t_infomask & 1024) > 0 THEN ' (c)'
WHEN (t_infomask & 2048) > 0 THEN ' (a)'
ELSE ''
END AS xmax,
t_ctid
FROM heap_page_items(get_raw_page(relname,pageno))
ORDER BY lp;
$$ LANGUAGE SQL;
á€áá¯á¶á á¶ááœááºá á¡áááºážáá¬ážááŸááºážá áá±á«ááºážá á®ážááœáẠááŒá áºáá»ááºáá±áááºááŸá¬ ááá¯ááá¯ááŸááºážáááºážáááº-
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+------+-------+--------
(0,1) | normal | 3664 | 0 (a) | (0,1)
(1 row)
áááºáá°áá±á¬áºáááºáž áááááá¬áá¬á¡áá±ážá áááºáááºážáá±á¬ á¡áá»ááºá¡áááºáá»á¬ážááᯠpseudo-columns xmin ááŸáá·áº xmax ááᯠá¡áá¯á¶ážááŒá¯á ááá¬ážááá¯ááºááá¯ááºá ááá°ááá¯ááºáá«áááºá
=> SELECT xmin, xmax, * FROM t;
xmin | xmax | id | s
------+------+----+-----
3664 | 0 | 1 | FOO
(1 row)
fixation
ááœá±áá±ážááœá±áá°áá áºáᯠá¡á±á¬ááºááŒááºá áœá¬ááŒá®ážááŒá±á¬ááºáá«áá áááºážá á¡ááŒá±á¡áá±ááᯠááŸááºáá¬ážáá¬ážááẠááá¯á¡ááºááẠ- áááºážááᯠáááááŒá¯áá¬ážááŒá±á¬ááºáž áááááŒá¯áá«á áá«ááá¯áá¯ááºááá¯á·á XACT ááá¯á· áá±á«áºáá²á· ááœá²á·á ááºážáá¯á¶ááᯠá¡áá¯á¶ážááŒá¯ááŒá®áž (áá¬ážááŸááºáž 10 áááá¯ááºáááºá CLOG (commit log) ááá¯á· áá±á«áºááŒá®áž áá®áá¬áááºááᯠáá±áá¬á¡áá»áá¯ážáá»áá¯ážááŸá¬ ááœá±á·ááá¯ááºáá«áá±ážáááº)á
XACT ááẠá áá áºáááºááá±á¬ááºááá¬ážááá¯ááºáá«á á€á¡áá¬áá»á¬ážááẠPGDATA/pg_xact áááºážááœáŸááºááŸá ááá¯ááºáá»á¬ážááŒá áºáááºá áááºážááá¯á·ááœáẠááœá±áá±ážááœá±áá°áá áºáá¯á á®á¡ááœáẠáá áºááŸá áºáá¯áá«ááŸááááº- áááááŒá¯áá¬ážááŒá®ážá áá»ááºááááºážáá¬ážáááº- á¡áááºážáá¬ážááŸááºážáá±á«ááºážá á®ážááœááºáá²á·ááá¯á·áááºá á€á¡áá»ááºá¡áááºááᯠá¡áááºááŒá±á á±áááºá¡ááœááºáᬠááá¯ááºá¡áá»á¬ážá¡ááŒá¬ážááá¯á· ááá¯ááºážááŒá¬ážáá¬ážáá«áááºá á¡á±ážáá²ááẠá ááºážá á¬ážáá±á¬á¡áá«ááœáẠáá»áœááºá¯ááºááá¯á·ááẠá€ááŒá¿áá¬ááá¯á· ááŒááºááœá¬ážáá«áááºá á€ááá¯ááºáá»á¬ážááŸáá·áºá¡áá° á¡áá¯ááºááẠá¡ááŒá¬ážáá°áá»á¬ážá¡á¬ážáá¯á¶ážáá²á·ááá¯á· á á¬áá»ááºááŸá¬áá áºáá¯ááŒá®ážáá áºáᯠáá¯ááºáá±á¬ááºáá«áááºá
ááá¯á·ááŒá±á¬áá·áºá XACT ááœáẠááœá±áá±ážááœá±áá°áá áºáá¯ááᯠáááááŒá¯áá±á¬á¡áá«á áááááŒá¯áá¬ážáá±á¬áá áºááᯠá€ááœáŸá²ááŒá±á¬ááºážááŸá¯á¡ááœáẠáááºááŸááºáááºá á€áááºááŸá¬ áááááŒá¯á ááºá¡ááœááºáž ááŒá áºáá»ááºáá²á·ááá»áŸ (ááŒáá¯áááºááŸááºáááºážáááºááŒááºážááŸááºáááºážá¡ááŒá±á¬ááºáž áá»áœááºá¯ááºááá¯á· áááŒá±á¬ááá±ážáá±á¬áºáááºáž)á
á¡ááŒá¬ážááœá±áá±ážááœá±áá°áá¯ááºáááºážááẠáá»áœááºá¯ááºááá¯á·ááŒáá·áºááŸá¯áá²á·ááá·áº ááá¬ážá á¬áá»ááºááŸá¬ááá¯á· áááºáá±á¬ááºááá·áºá¡áá«á áá±ážááœááºážáá»á¬ážá áœá¬ááᯠááŒá±ááá¯ááááºááŒá áºáááºá
- xmin á¡áá±á¬ááºážá¡ááẠááŒá®ážááœá¬ážááŒá®áá¬ážá ááá¯ááºáá«áá áááºáá®ážáá¬ážáá±á¬ á
á¬ááŒá±á¬ááºážááá¬ážááŸááºážááᯠááŒááºááá¯ááºáááºááá¯ááºáá±á
á€á á áºáá±ážááŸá¯ááᯠá á¶ááá°áá¬á áá»áŸáá±ááŸááºáá¬ááºááœáẠáááºááŸáááŒá®áž ProcArray áá¯áá±á«áºáá±á¬ á¡ááŒá¬ážááœá²á·á ááºážáá¯á¶á¡á¬áž ááŒáá·áºááŸá¯ááŒááºážááŒáá·áº áá¯ááºáá±á¬ááºáááºá áááºážááœáẠá¡áááºáááºáá±áá±á¬ áá¯ááºáááºážá ááºáá»á¬ážá¡á¬ážáá¯á¶ážáá á¬áááºážáá áºáá¯áá«ááŸáááŒá®áž áá áºáá¯á á®á¡ááœáẠáááºážááááºááŸá (áááºááŒáœáá±á¬) ááœáŸá²ááŒá±á¬ááºážááŸá¯á¡áá±á¡ááœááºááᯠááœáŸááºááŒáá¬ážáááºá - ááŒá®ážááœá¬ážáá«áá áááááááºááŒá¯ááŒááºáž ááá¯á·ááá¯áẠáááºáá»ááºááŒááºáž áááºáá²á·ááá¯á·áá¯ááºáá±á¬ááºáááºáááºážá áááºáá»ááºááá¯ááºáá»áŸáẠá¡áááºážáá¬ážááŸááºážááá¯áááºáž ááŒááºááá¯ááºáááºááá¯ááºáá±á
á€áááºááŸá¬ XACT á¡ááœááºá¡ááá¡áá»ááŒá áºáááºá ááá¯á·áá±á¬áºá XACT ááá±á¬ááºáá¯á¶ážá á¬áá»ááºááŸá¬áá»á¬ážááᯠRAM ááœááºááŒá¬ážáá¶áá»á¬ážááœááºááááºážáááºážáá¬ážáá±á¬áºáááºážá á¡áá»áááºááá¯ááºáž XACT á á áºáá±ážáááºá á»á±ážááŒá®ážáá±áá±ážáááºá ááá¯á·ááŒá±á¬áá·áºá ááœá±áá±ážááœá±áá°á¡ááŒá±á¡áá±á¡á¬áž áá¯á¶ážááŒááºááŒá®ážáááºááŸáá·áº áááºážááᯠstring áá¬ážááŸááºážá xmin_committed ááŸáá·áº xmin_aborted bits áá»á¬ážááá¯á· á á¬áá±ážáá¬ážáááºá á€áá áºáá»á¬ážáá²á០áá áºáá¯ááᯠáááºááŸááºáá«áá ááœá±áá±ážááœá±áá° xmin á¡ááŒá±á¡áá±ááᯠááááŒá®áž áá±á¬ááºáá áºáá±á·ááœáẠááœá±áá±ážááœá±áá° XACT ááᯠáááºáá±á¬ááºááẠáááá¯á¡ááºáá«á
á¡áá±á¬ááºážá¡áááºááá¯ááºááá¯ááºá á€áá áºáá»á¬ážááᯠá¡áááºááŒá±á¬áá·áº ááá·áºááœááºážááŒááºážáááŒá¯ááááºážá ááá·áºááœááºážááŸá¯áá áºáᯠáá±á«áºáá±á«ááºáá¬áá±á¬á¡áá«ááœáẠá¡áá±á¬ááºážá¡ááẠá¡á±á¬ááºááŒááºáááºááá¯áááºááᯠáááááá±ážáá±á áááááááºááŒá¯ááá·áºá¡áá»áááºááœáẠáááºááá·áºá á¬áá»ááºááŸá¬áá»á¬ážááᯠááŒá±á¬ááºážáá²áá²á·áááºááᯠááŸááºážááŸááºážáááºážáááºážáááááá±á ááá¯ááá¯á·áá±á¬ á á¬áá»ááºááŸá¬áá»á¬ážá áœá¬ ááŸáááá¯ááºáááºá áááºážááá¯á·ááᯠáá»ááºááŸááºááŒááºážááẠá¡áá»áá¯ážáááŒá áºááœááºážáá«á ááá¯á·á¡ááŒááºá á¡áá»áá¯á·áá±á¬á á¬áá»ááºááŸá¬áá»á¬ážááᯠááŒá¬ážáá¶áááºááŸáºá០disk ááá¯á· ááŸááºáá¯ááºááá¯ááºáááºá bits áá»á¬ážááᯠááŒá±á¬ááºážáá²ááẠáááºážááá¯á·ááᯠáááºáá¶áááºááŸá¯ááŒááºážááẠcommit ááᯠáááááá¬áᬠááŸá±ážááœá±ážá á±áá«áááºá
ááœá±á á¯ááŒááºážá á¡á¬ážáááºážáá»ááºááŸá¬ á¡ááŒá±á¬ááºážá¡áá²áá»á¬ážááŒá®ážáá±á¬ááºá áááºááá·áºááœá±áá±ážááœá±áá° (ááá¯ážááŸááºážáá±á¬áááºááŸá¯ááŒááºáž - SELECT ááá¯áá¯ááºáá±á¬ááºáá±ááá·áºááá¯ááº) ááẠááŒá¬ážáá¶áááºááŸáºááŸá áá±áá¬á á¬áá»ááºááŸá¬áá»á¬ážááᯠá áááºááŒá±á¬ááºážáá²ááá¯ááºááẠá
áá®áá±á¬á· á¡ááŒá±á¬ááºážá¡áá²ááᯠááŒááºááŒáá¡á±á¬ááºá
=> COMMIT;
á á¬áá»ááºááŸá¬áá±á«áºááœáẠáá¬ááŸáááŒá±á¬ááºážáá²áá±ážáá« (ááá¯á·áá±á¬áº ááœá±áá±ážááœá±áá°á¡ááŒá±á¡áá±á¡á¬áž XACT ááœáẠááŸááºáááºážáááºáá¬ážááŒá®ážááŒá áºááŒá±á¬ááºáž áá»áœááºá¯ááºááá¯á·áááááº)
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+------+-------+--------
(0,1) | normal | 3664 | 0 (a) | (0,1)
(1 row)
ááᯠá á¬áá»ááºááŸá¬ááᯠááááá¯á¶ážáááºáá±á¬ááºááá·áº ááœá±áá±ážááœá±áá°ááẠxmin ááœá±áá±ážááœá±áá° á¡ááŒá±á¡áá±ááᯠáá¯á¶ážááŒááºááŒá®áž á¡áá»ááºá¡ááẠbits ááœáẠáá±ážááá«áááº-
=> SELECT * FROM t;
id | s
----+-----
1 | FOO
(1 row)
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+-------+--------
(0,1) | normal | 3664 (c) | 0 (a) | (0,1)
(1 row)
áááºááŸá¬ážáá±áž
á¡áááºážáá áºáá¯ááᯠáá»ááºááá¯ááºáá±á¬á¡áá«ááœááºá áááºááŸá áá¬ážááŸááºážá xmax á¡ááœááºááœáẠáááºááŸá áá»ááºááá¯ááºáá±á¬ ááœá±áá±ážááœá±áá° á¡áá±á¡ááœááºááᯠáá±ážááŸááºáá¬ážááŒá®áž xmax_aborted bit ááᯠááŸááºážáá¬ážáááºá
áááºááŒáœáá±á¬ ááœá±áá±ážááœá±áá°ááŸáá·áº áááºááá¯ááºáá±á¬ xmax á áááºááŸááºáááºááá¯ážááẠá¡áááºážáá±á¬á·ááºá¡ááŒá Ạáá¯ááºáá±á¬ááºáááºááᯠáááááŒá¯áá«á á¡ááŒá¬ážááœá±áá±ážááœá±áá°á á€á¡áááºážááᯠá¡ááºááááºáá¯ááºááẠááá¯á·ááá¯áẠáá»ááºááá¯áá«áá ááœá±áá±ážááœá±áá° xmax ááᯠá¡ááŒá®ážáááºááẠá á±á¬áá·áºááá¯ááºážáááá·áºáááºá ááááºááá¯á·ááŒááºážá¡ááŒá±á¬ááºáž áá±á¬ááºááŸááŒá±á¬áá«áááºá ááá¯á¡áá»áááºááœááºá á¡áááºážáá±á¬á·áááºááá·áºá¡áá±á¡ááœááºááŸá¬ á¡ááá·áºá¡áááºáááŸáááŒá±á¬ááºáž áá»áœááºá¯ááºááá¯á·áááááŒá¯áááá«áááºá áááºážááá¯á·ááẠRAM ááœáẠáá±áá¬ááœááºááá°áá² á áá áºá áœááºážáá±á¬ááºáááºááẠáááºážááá¯á·ááá¶áá«ááºááᯠáááááá¯ááºá á±áá«á ááŸááºáá«áááºá âááŸááºâ áá±á¬ á¡áá±á¬ááºážá¡áááºáá»á¬ážááœáẠá¡ááŒá¬ážá¡á¬ážáááºážáá»ááºáá»á¬áž ááŸááááºá ááá¯á·áá±á¬áº áá±á¬ááºááá¯ááºážááœáẠááá¯áá»á¬ážáááºá
ááá¯ááºážááᯠáá»ááºááá¯ááºáá¡á±á¬ááºá
=> BEGIN;
=> DELETE FROM t;
=> SELECT txid_current();
txid_current
--------------
3665
(1 row)
ááœá±áá±ážááœá±áá°áá¶áá«ááºááᯠxmax á¡ááœááºááœáẠáá±ážáá¬ážáááºááᯠáá»áœááºá¯ááºááá¯á·ááœá±á·ááŒááºááá±á¬áºáááºáž á¡áá»ááºá¡ááẠbits áá»á¬ážááᯠáááºááŸááºááá¬ážáá«á
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+------+--------
(0,1) | normal | 3664 (c) | 3665 | (0,1)
(1 row)
áá»ááºááŒááºáž
á¡ááŒá±á¬ááºážá¡áá²áá»á¬ážááᯠáá»ááºáá áºááŒááºážááẠáá»á°ážááœááºááŒááºážááŸáá·áº á¡áá¬ážáá°áá¯ááºáá±á¬ááºáááºá XACT ááœááºáᬠáá»ááºááááºážáá¬ážáá±á¬áá áºááᯠááœá±áá±ážááœá±áá°á¡ááœáẠáááºááŸááºáá¬ážáááºá áááºáá»ááºááŒááºážááẠáááááááºáá²á·ááá¯á· ááŒááºáááºáááºá á¡áááá·áºááᯠROLLBACK áá¯áá±á«áºáá±á¬áºáááºážá á¡ááŒá±á¬ááºážá¡áá²áá»á¬ážááᯠáá±á¬ááºááŒááºáá¯ááºáááºááá¯ááºáá«- áá±áá¬á á¬áá»ááºááŸá¬áá»á¬ážááœáẠá¡áá±á¬ááºážá¡áááºááŒá¯áá¯ááºááẠá á®áá¶áá¬ážááá·áºá¡áá¬á¡á¬ážáá¯á¶ážááẠáááŒá±á¬ááºážáá²áá«á
=> ROLLBACK;
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+------+--------
(0,1) | normal | 3664 (c) | 3665 | (0,1)
(1 row)
á á¬áá»ááºááŸá¬ááᯠáááºáá±á¬ááºááá·áºá¡áá«á á¡ááŒá±á¡áá±ááᯠá á áºáá±ážáááºááŒá áºááŒá®áž xmax_aborted á¡ááááºá¡ááŒáœááºááᯠá¡áááºážáá¬ážááŸááºážááá¯á· áááºááŸááºáááºááŒá áºáááºá xmax áá¶áá«ááºááẠá á¬áá»ááºááŸá¬áá±á«áºááœáẠááŸááá±áá±á¬áºáááºáž áááºážááᯠáááºáá°áá»áŸ ááŒáá·áºáááºááá¯ááºáá«á
=> SELECT * FROM t;
id | s
----+-----
1 | FOO
(1 row)
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+----------+--------
(0,1) | normal | 3664 (c) | 3665 (a) | (0,1)
(1 row)
update ááá¯
á¡ááºááááºááẠá¡áááºážá áááºááŸááá¬ážááŸááºážááᯠááááŠážá áœá¬ áá»ááºááŒá®ážáá±á¬áẠá¡áá áºáá áºáá¯ááᯠááá·áºááœááºážááá²á·ááá¯á· á¡áá¯ááºáá¯ááºáááºá
=> BEGIN;
=> UPDATE t SET s = 'BAR';
=> SELECT txid_current();
txid_current
--------------
3666
(1 row)
áá±ážááœááºážááẠá á¬ááŒá±á¬ááºážáá áºááŒá±á¬ááºáž (áá¬ážááŸááºážá¡áá áº) áá¯ááºáá±ážáááº-
=> SELECT * FROM t;
id | s
----+-----
1 | BAR
(1 row)
ááá¯á·áá±á¬áº á á¬áá»ááºááŸá¬ááœáẠáá»áœááºá¯ááºááá¯á·ááẠáá¬ážááŸááºážááŸá áºáá»áá¯ážáá¯á¶ážááᯠááœá±á·ááááº-
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+-------+--------
(0,1) | normal | 3664 (c) | 3666 | (0,2)
(0,2) | normal | 3666 | 0 (a) | (0,2)
(2 rows)
áá»ááºááá¯ááºáá±á¬áá¬ážááŸááºážááᯠxmax á¡ááœááºááœáẠáááºááŸáááœá±áá±ážááœá±áá°áá¶áá«ááºááŒáá·áº á¡ááŸááºá¡áá¬ážááŒá¯áá¬ážáááºá ááá¯á·á¡ááŒááºá ááááºááœá±áá±ážááœá±áá°ááᯠáááºáá»ááºááá¯ááºáá±á¬ááŒá±á¬áá·áº á€áááºááá¯ážááᯠá¡áá±á¬ááºážáá±á«áºááœáẠáá±ážáá¬ážáááºá áááºááŸá ááœá±áá±ážááœá±áá° á¡ááŒá±á¡áá±ááᯠáááááá±ážáá±á¬ááŒá±á¬áá·áº xmax_aborted bit ááᯠááŸááºážáááºážáá¬ážáááºá
ááᯠá á¬ááŒá±á¬ááºážá ááááá¬ážááŸááºážááẠáá¯áááá¡áá Ạ(t_ctid á¡ááœááº) ááᯠáááºááœáŸááºážáááºá
áá¯áááá¡ááœáŸááºážááẠá¡ááœáŸááºážá á¬áá»ááºááŸá¬ááœáẠáá±á«áºáá¬ááŒá®áž áá¯ááááááºážáá áºáá¯ááẠááá¬ážá á¬áá»ááºááŸá¬ááŸá áá¯ááááá¬ážááŸááºážááᯠáááºááœáŸááºážáááºá
áá»ááºááŒááºážáá²á·ááá¯á·áááºá á¡áááºážáááááá¬ážááŸááºážááŸá xmax áááºááá¯ážááẠá¡áááºážá¡á¬áž áá±á¬á·ááºáá»áá¬ážááŒá±á¬ááºáž ááœáŸááºááŒáá±áááºá
áá±á¬ááºážááŒá®á ááœá±áá±ážááœá±áá°ááᯠá¡ááŒá®ážáááºááá¯ááºáá¡á±á¬ááºá
=> COMMIT;
á¡ááœáŸááºážááááºáž
á¡áá¯áááá±á¬á· ááá¬ážá á¬áá»ááºááŸá¬ááœá±áá±á¬ááºáá² ááŒá±á¬ááŒá áºáá±ážáááºá á¡ááœáŸááºážááááºážáá»á¬ážá¡ááœááºáž áá¬ááŒá áºááœá¬ážááá²á
á¡ááœáŸááºážá á¬áá»ááºááŸá¬áá»á¬ážááŸá á¡áá»ááºá¡áááºáá»á¬ážááẠáá®ážááŒá¬ážá¡ááœáŸááºážá¡áá»áá¯ážá¡á á¬ážáá±á«áºáá°áááºá áá»á¬ážá áœá¬ááœá²ááŒá¬ážáá«áááºá á¡ááœáŸááºážá¡áá»áá¯ážá¡á á¬ážáá áºáá¯áááºáá»áŸáẠá á¬áá»ááºááŸá¬á¡áá»áá¯ážá¡á á¬ážáá»á¬áž ááœá²ááŒá¬ážáá«áááºá á¥ááá¬á¡á¬ážááŒáá·áºá B-tree ááœáẠmetadata á á¬áá»ááºááŸá¬ááŸáá·áº "áá¯á¶ááŸááº" á á¬áá»ááºááŸá¬áá»á¬ážááŸááááºá
ááá¯á·áá±á¬áºá á á¬áá»ááºááŸá¬ááœáẠá¡áá»á¬ážá¡á¬ážááŒáá·áº á¡áááºážáá»á¬ážááŸáá·áº á¡áááºážáá»á¬ážááá¯ááºááá¯áẠ(ááá¬ážá á¬áá»ááºááŸá¬áá²á·ááá¯á·) ááœáŸááºááŒááá·áº array áá áºáá¯ááŸááááºá ááá¯á·á¡ááŒááºá á á¬áá»ááºááŸá¬áá¡áá¯á¶ážááœáẠá¡áá°ážáá±áá¬á¡ááœáẠáá±áá¬ááœááºááŸááááºá
á¡ááœáŸááºážááááºážáá»á¬ážááœáẠá¡áááºážáá»á¬ážááẠá¡ááœáŸááºážá¡áá»áá¯ážá¡á á¬ážáá±á«áºáá°áááºá á¡ááœááºááœá²ááŒá¬ážáá±á¬ááœá²á·á ááºážáá¯á¶áá»á¬áž ááŸáááá¯ááºáááºá á¥ááá¬á¡á¬ážááŒáá·áºá B-tree áá áºáá¯á¡ááœááºá á¡ááœááºá á¬áá»ááºááŸá¬áá»á¬ážááŸáá·áºáááºááá¯ááºááá·áºá¡áááºážáá»á¬ážááœáẠáááºááá¯ááºáá¬ááá¬ážá¡áááºážá¡ááœáẠá¡ááœáŸááºážááááºážáá±á¬á·áááºááá¯ážááŸáá·áº ááá¯ážáá¬ážáá»áẠ(ctid) áá«ááŸááááºá áá±áá°áá»á¡á¬ážááŒáá·áºá á¡ááœáŸááºážááááºážááᯠáá¯á¶ážáááœá²ááŒá¬ážáá±á¬áááºážáááºážááŒáá·áº áááºáá±á¬ááºááá¯ááºáááºá
á¡áá±ážááŒá®ážáá¯á¶ážá¡áá»ááºááŸá¬ áááºááá·áºá¡áá»áá¯ážá¡á á¬ážá á¡ááœáŸááºážáá»á¬ážááœáẠá¡áááºážáá¬ážááŸááºážáá»á¬áž áááŸááá«á ááá¯á·ááá¯ááºáá«á á á¬ááŒá±á¬ááºážáá áºáá¯á á®ááᯠáá¬ážááŸááºážá¡ááá¡áá»ááŒáá·áº ááá¯ááºá á¬ážááŒá¯áááºáᯠáá»áœááºá¯ááºááá¯á· áá°áááá¯ááºáááºá áá áºáááºážááá¯ááá±á¬áº á¡ááœáŸááºážá¡áááºážáá±á«ááºážá á®ážááœáẠxmin ááŸáá·áº xmax á¡ááœááºáá»á¬áž áááŸááá«á á¡ááœáŸááºážááááºážáá»á¬ážá០ááá·áºááºáá»á¬ážááẠá¡áááºážáá»á¬ážá ááá¬ážáá¬ážááŸááºážá¡á¬ážáá¯á¶ážááá¯á· áŠážáááºááœá¬ážáááºáᯠáá»áœááºá¯ááºááá¯á· áá°áááá¯ááºááẠ- ááá¯á·ááŒá±á¬áá·áº ááá¬ážááá¯ááŒáá·áºáá¯á¶ááŒáá·áº áááºááá·áºááœá±áá±ážáá»á±ááŸá¯ááœáẠááœá±á·ááááºááᯠáááºááŸá¬ááœá±ááá¯ááºáá«áááºá (á¡ááŒá²áááºážá¡áá±ááŒáá·áºá áááºážááẠá¡ááŸááºááá¬ážáá áºáá¯áá¯á¶ážááá¯ááºáá«á á¡áá»áá¯á·ááá á¹á áá»á¬ážááœááºá ááŒááºááá¯ááºá áœááºážááŒá±áá¯á¶ááẠáá¯ááºáááºážá ááºááᯠá¡áá±á¬ááºážáá¯á¶ážááŒá áºá¡á±á¬áẠáá¯ááºáá±á¬ááºááá¯ááºáá±á¬áºáááºáž áááºážááᯠáá±á¬ááºááá¯ááºážááœáẠá¡áá±ážá áááºááŒáá·áºááŸá¯áá«áááºá)
áá áºáá»áááºáááºážááŸá¬áááºá á¡ááœáŸááºážá á¬áá»ááºááŸá¬ááœáẠáááºááŸááá¬ážááŸááºážááŸáá·áº á¡áá±á¬ááºážááŸá áºáá¯á áá¯á¶ážá¡ááœáẠááœáŸááºááŒáá»ááºáá»á¬ážááᯠáá»áœááºá¯ááºááá¯á· ááœá±á·ááŸááááº-
=> SELECT itemoffset, ctid FROM bt_page_items('t_s_idx',1);
itemoffset | ctid
------------+-------
1 | (0,2)
2 | (0,1)
(2 rows)
á¡áá¯á¡áá±á¬ááºáá»á¬áž
áááºááœá±á·ááœááºá PostgreSQL ááẠáááºážá¡á¬áž ááœáŸá²ááŒá±á¬ááºážáá±ážááá·áºáá¶áá«ááºáá»á¬ážááᯠ"ááááºážáááºážáááº" ááœáá·áºááŒá¯ááá·áº ááá¯ááá¯áá±á¬ááºážááœááºá¡á±á¬ááºáá¯ááºáá±á¬ááºááŸá¯áá»á¬ážááᯠá¡áá¯á¶ážááŒá¯áááºá
ááœá±áá±ážááœá±áá°áá áºáá¯ááẠáá±áá¬ááá¯áá¬áááºáá«áá á¡áááºážáá¬ážááŸááºážáá»á¬ážá ááŒááºááá¯ááºá áœááºážá¡áá±á«áº áááºáá±á¬ááºááŸá¯áááŸááá«á ááá¯á·ááŒá±á¬áá·áºá áááºáá±á¬ááºááŸá¯áá¯ááºáááºážá ááºááẠááœá±áá±ážááœá±áá°á¡ááœáẠvirtual xid ááᯠáŠážá áœá¬áá¯ááºáá±ážáááºá áá¶áá«ááºááœáẠáá¯ááºáááºážá áẠID ááŸáá·áº áá¶áá«ááºá ááºáá áºáᯠáá«áááºáá«áááºá
á€áá¶áá«ááºááᯠáá¯ááºáá±ážááŒááºážááẠáá¯ááºáááºážá ááºá¡á¬ážáá¯á¶ážááŒá¬ážááœáẠáááºáá°ááŒá¯ááŒááºáž áááá¯á¡ááºáá±á¬ááŒá±á¬áá·áº á¡ááœááºááŒááºáááºáá«áááºá á¡á±ážáá²ááŒááºážá¡ááŒá±á¬ááºážááŒá±á¬áá±á¬á¡áá«ááœáẠáááááá¶áá«ááºáá»á¬ážááᯠá¡áá¯á¶ážááŒá¯áááá·áº á¡ááŒá¬ážá¡ááŒá±á¬ááºážáááºážáá áºáá¯ááŸáá·áº áá»áœááºá¯ááºááá¯á· áááá¬áá«áááºá
áá±áá¬áá»áŸááºáá áºááŒááºáá»á¬ážááœáẠáááºááá·áºáááºážááŒáá·áºáááᯠááááºážááááºážá¡áá¯áá»á¬ážááᯠááá·áºááœááºážá ááºážá á¬ážáááºááá¯ááºáá«á
á¡áá»áááºááŸáá·áºá¡áá»áŸ ááá°áá®áá±á¬á¡áá»ááºáá»á¬ážááœááºá á¡áá¯á¶ážááŒá¯ááŒá®ážáá±á¬ áá¶áá«ááºáá»á¬ážááŒáá·áº á áá áºááœáẠá¡áá¯á¡áá±á¬áẠá¡áá±á¬ááºážá¡áááºáá»á¬áž ááŸáááá¯ááºáááºá áááºážááẠáá¯á¶ááŸááºááŒá áºáááºá ááá¯á·áá±á¬áº ááá¯áá¶áá«ááºááᯠáá±áá¬á á¬áá»ááºááŸá¬áá»á¬ážááœáẠáá±ážáá¬ážááááá«á á¡áááºááŒá±á¬áá·áºááá¯áá±á¬áº á á¬áá»ááºááŸá¬ááᯠáá±á¬ááºáá áºááŒáááºáááºáá±á¬ááºááá·áºá¡áá«ááœáẠáááºážááẠá¡áááá¹áá«ááºá¡á¬ážáá¯á¶ážááᯠáá¯á¶ážááŸá¯á¶ážááœá¬ážááá¯ááºáááºá
=> BEGIN;
=> SELECT txid_current_if_assigned();
txid_current_if_assigned
--------------------------
(1 row)
ááœá±áá±ážááœá±áá°áá áºáá¯ááẠáá±áá¬ááᯠá áááºááŒá±á¬ááºážáá²áá«áá áááºážááᯠá¡á á áºá¡ááŸááºáá°ážááŒá¬ážáá±á¬ ááœá±áá±ážááœá±áá°áá¶áá«ááºáá áºáá¯áá±ážáá¬ážáááºá
=> UPDATE accounts SET amount = amount - 1.00;
=> SELECT txid_current_if_assigned();
txid_current_if_assigned
--------------------------
3667
(1 row)
=> COMMIT;
Nested ááœá±ááœáŸá²ááŸá¯áá»á¬áž
á¡ááŸááºáá»á¬ážááááºážáááºážáá«á
SQL ááœááºáááºááŸááºáá¬ážáááºá á¡ááŸááºáá»á¬ážááááºážáááºážáá«á (savepoint) ááẠááœá±áá±ážááœá±áá°á áá áºá áááºáá áºááá¯ááºážááᯠáá¯á¶ážáááŸá±á¬ááºááŸááºááŒááºážáááŸááá² áááºáá»ááºááá¯ááºá á±ááá·áº (savepoint)á ááá¯á·áá±á¬áºá ááœá±áá±ážááœá±áá°ááẠáááºážáááŒá±á¬ááºážáá²ááŸá¯á¡á¬ážáá¯á¶ážá¡ááœáẠáá°áá®áá±á¬á¡ááŒá±á¡áá±ááŸáááŒá®ážá áá±áá¬ááᯠáá¯ááºááá¯ááºážááá¯ááºáá¬á¡á ááŒááºááœáá·áºáááºááá¯ááºáá±á¬ááŒá±á¬áá·áº áááºážááẠá¡áááºáá±á¬áºááŒáá«áá¯á¶ááŸáá·áº áááá¯ááºáá®áá«á
á€áá¯ááºáá±á¬ááºáá»ááºááᯠá¡áá±á¬ááºá¡áááºáá±á¬áºáááºá savepoint áá áºáá¯ááŸáá·áº ááœá±áá±ážááœá±áá°ááᯠáá®ážááŒá¬ážáá»á¬ážá áœá¬ááœá²áá¬ážáááºá nested á¡áá±á¬ááºážá¡áááºáá»á¬áž (subtransaction) áá®ážááŒá¬ážá á® á á®áá¶ááá·áºááœá²ááá¯ááºááá·áº á¡ááŒá±á¡áá±á
Nested ááœá±áá±ážááœá±áá°áá»á¬ážááœáẠáááºážááá¯á·áááá¯ááºááá¯ááºáá¶áá«ááºááŸáááẠ(áááºáááœá±áá±ážááœá±áá°á¡áá±á¡ááœááºááẠááá¯áá»á¬ážáááº)á XACT ááœáẠnested á¡áá±á¬ááºážá¡áááºáá»á¬ážá á¡ááŒá±á¡áá±ááᯠáá¯á¶ááŸááºá¡ááá¯ááºáž ááŸááºáááºážáááºáá¬ážáá±á¬áºáááºáž áá±á¬ááºáá¯á¶ážá¡ááŒá±á¡áá±ááẠáááºáááœá±áá±ážááœá±áá°á á¡ááŒá±á¡áá±áá±á«áºááœáẠáá°áááºáááº- áááºážááᯠáááºáá»ááºáá«áá ááá¯á·áá±á¬ááºááœáẠá¡á á¯á ááºááœá±áá±ážáá»á±ááŸá¯á¡á¬ážáá¯á¶ážááá¯áááºáž áááºáá»ááºáá«áááºá
ááœá±áá±ážááœá±áá° nesting á¡ááŒá±á¬ááºáž á¡áá»ááºá¡áááºááᯠPGDATA/pg_subtrans directory á¡ááœááºážááŸá ááá¯ááºáá»á¬ážááœáẠááááºážáááºážáá¬ážáááºá ááá¯ááºáá»á¬ážááᯠXACT buffers áá»á¬ážáá²á·ááá¯á·ááẠá á¯á ááºážáá¬ážááá·áº instance á áá»áŸáá±áá¬ážáá±á¬ memory ááŸá buffers ááŸáááá·áº áááºáá±á¬ááºááŒáá·áºááŸá¯áá«áááºá
ááá¯ááºááá¯ááºá¡á¯ááºáá»á¯ááºááœáá·áºááŸááá±á¬ ááœá±áá±ážááœá±áá°áá»á¬ážááŒáá·áº nested ááœá±áá±ážááœá±áá°áá»á¬ážááᯠááá±á¬ááœá±ážáá«ááŸáá·áºá ááá¯ááºááá¯ááºá¡á¯ááºáá»á¯ááºááœáá·áºáááœá±áá±ážááœá±áá°áá»á¬ážááẠáá áºáŠážááŸáá·áºáá áºáŠážá¡áá±á«áºááœáẠáááºááá¯á·áá»áŸááá°áááºáá±á¬áºáááºážá áá¯á¶ááŸáẠPostgreSQL ááœáẠááá¯ááºááá¯ááºá¡á¯ááºáá»á¯ááºááœáá·áºáááœá±áá±ážááœá±áá°áá»á¬ážáááŸááá« á á¡áá±á¬ááºážáá¯á¶ážááŒá áºáá±á¬ááºážááŒá áºááá¯ááºáááº- áááºážááá¯á·ááẠá¡ááœááºááá¯á¡ááºááŒá®áž á¡ááŒá¬áž DBMS áá»á¬ážááœáẠáááºážááá¯á·áááŸááá±ááŒááºážááẠá¡ááœá²áá¯á¶ážá á¬ážááŸá¯ááᯠááŸáá¯ážáá±á¬áºá á±áááºá
ááá¬ážááá¯ááŸááºážáá¡á±á¬ááºá ááœá±áá±ážááœá±áá°áá áºáá¯á áááºááŒá®áž á¡áááºážááá¯ááá·áºááŒáá«á áá¯á·á
=> TRUNCATE TABLE t;
=> BEGIN;
=> INSERT INTO t(s) VALUES ('FOO');
=> SELECT txid_current();
txid_current
--------------
3669
(1 row)
=> SELECT xmin, xmax, * FROM t;
xmin | xmax | id | s
------+------+----+-----
3669 | 0 | 2 | FOO
(1 row)
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+------+-------+--------
(0,1) | normal | 3669 | 0 (a) | (0,1)
(1 row)
á¡áᯠsave point áá áºáá¯áááºááŒá®áž áá±á¬ááºááá¯ááºážáá áºáá¯ááá·áºááá¯ááºáá¡á±á¬ááºá
=> SAVEPOINT sp;
=> INSERT INTO t(s) VALUES ('XYZ');
=> SELECT txid_current();
txid_current
--------------
3669
(1 row)
txid_current() áá¯ááºáá±á¬ááºáá»ááºááẠnested á¡áá±á¬ááºážá¡áááºáá¶áá«ááºááá¯ááºáá² áááºáááœá±áá±ážááœá±áá°áá¶áá«ááºááᯠááŒááºáá±ážááŒá±á¬ááºáž áááááŒá¯áá«á
=> SELECT xmin, xmax, * FROM t;
xmin | xmax | id | s
------+------+----+-----
3669 | 0 | 2 | FOO
3670 | 0 | 3 | XYZ
(2 rows)
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+------+-------+--------
(0,1) | normal | 3669 | 0 (a) | (0,1)
(0,2) | normal | 3670 | 0 (a) | (0,2)
(2 rows)
save point ááá¯á· ááŒááºááŸáá·áºááŒá®áž ááááá á¬ááŒá±á¬ááºážááᯠááá·áºááŒáá«á áá¯á·á
=> ROLLBACK TO sp;
=> INSERT INTO t(s) VALUES ('BAR');
=> SELECT xmin, xmax, * FROM t;
xmin | xmax | id | s
------+------+----+-----
3669 | 0 | 2 | FOO
3671 | 0 | 4 | BAR
(2 rows)
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+-------+--------
(0,1) | normal | 3669 | 0 (a) | (0,1)
(0,2) | normal | 3670 (a) | 0 (a) | (0,2)
(0,3) | normal | 3671 | 0 (a) | (0,3)
(3 rows)
á á¬áá»ááºááŸá¬ááœáẠáááºáá»ááºáá¬ážáá±á¬ nested ááœá±áá±ážááœá±áá°ááŒáá·áº ááá·áºáá¬ážáá±á¬ á¡áááºážááᯠáá»áœááºá¯ááºááá¯á· áááºáááºááŒááºáá±ááá«áááºá
á¡ááŒá±á¬ááºážá¡áá²ááœá±ááᯠáá»áœááºáá±á¬áºááá¯á· ááŒááºáááºá
=> COMMIT;
=> SELECT xmin, xmax, * FROM t;
xmin | xmax | id | s
------+------+----+-----
3669 | 0 | 2 | FOO
3671 | 0 | 4 | BAR
(2 rows)
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+-------+--------
(0,1) | normal | 3669 (c) | 0 (a) | (0,1)
(0,2) | normal | 3670 (a) | 0 (a) | (0,2)
(0,3) | normal | 3671 (c) | 0 (a) | (0,3)
(3 rows)
ááᯠnested ááœá±áá±ážááœá±áá°áá áºáá¯á á®ááœáẠáááºážáááá¯ááºááá¯ááºá¡ááŒá±á¡áá±ááŸáááŒá±á¬ááºáž ááŸááºážááŸááºážáááºážáááºáž ááááŒááºááá¯ááºáá«ááŒá®á
ááá·áºááœááºážáá¬ážáá±á¬ ááœá±áá±ážááœá±áá°áá»á¬ážááᯠSQL ááœáẠááŒááºáá¬ážá áœá¬ á¡áá¯á¶ážáááŒá¯ááá¯ááºáááºááᯠáááááŒá¯áá« á ááá¯ááá¯áááºááŸá¬ áááºááẠáááºááŸáááᯠáááŒá®ážááŒá±á¬ááºáá² ááœá±áá±ážááœá±áá°á¡áá áºáá áºáᯠá áááºááá¯ááºáááºááá¯ááºááŒá±á¬ááºáž áááááŒá¯áá«á savepoints áá»á¬ážá¡ááŒáẠPL/pgSQL ááŒáœááºážáá»ááºáá»á¬ážááŸáá·áº á¡ááŒá¬ážáá±á¬ áá°ážááŒá¬ážáááºážááŒá¬ážáá±á¬ ááá á¹á áá»á¬ážá áœá¬ááᯠááá¯ááºááœááºááá·áºá¡áá«ááœáẠá€ááá¹ááá¬ážááẠááœááºááá¯ááºá áœá¬ á¡áááºáááºáá¬áá«áááºá
=> BEGIN;
BEGIN
=> BEGIN;
WARNING: there is already a transaction in progress
BEGIN
=> COMMIT;
COMMIT
=> COMMIT;
WARNING: there is no transaction in progress
COMMIT
áá¯ááºáá±á¬ááºáá»ááºáá»á¬ážá á¡ááŸá¬ážáá»á¬ážááŸáá·áº á¡áá¯ááŒá°áá¯á¶ážáá»á¬áž
áá¯ááºáá±á¬ááºáá»ááºáá áºáᯠáá¯ááºáá±á¬ááºáá±á áẠá¡ááŸá¬ážá¡ááœááºážáá áºáᯠááŒá áºáá±á«áºáá«á áááºááá¯á·ááŒá áºáááºáááºážá á¥ááá¬á á€áá²á·ááá¯á·áá±á¬á
=> BEGIN;
=> SELECT * FROM t;
id | s
----+-----
2 | FOO
4 | BAR
(2 rows)
=> UPDATE t SET s = repeat('X', 1/(id-4));
ERROR: division by zero
á¡ááŸá¬ážá¡ááœááºážáá áºáᯠááŒá áºááœá¬ážáá²á·áááºá ááᯠááœá±áá±ážááœá±áá°ááᯠáá»ááºááááºážááá¯ááºáááºáᯠáá°ááááŒá®áž áááºážááœáẠáááºááá·áºáá¯ááºáá±á¬ááºáá»ááºááá¯áá»áŸ ááœáá·áºáááŒá¯áá«á
=> SELECT * FROM t;
ERROR: current transaction is aborted, commands ignored until end of transaction block
á¡ááŒá±á¬ááºážá¡áá²áá»á¬ážááᯠáá»á°ážááœááºááẠááŒáá¯ážá á¬ážáá±á¬áºáááºážá PostgreSQL ááẠáá»ááºáá»ááŒá±á¬ááºáž á¡á á®áááºáá¶áá«áááºá
=> COMMIT;
ROLLBACK
áá»ááºááœááºááŒá®ážáá±á¬áẠááœá±áá±ážááœá±áá°áá áºáᯠá¡áááºááŒá±á¬áá·áº áááºáááºááá¯ááºáá±á¬ááºááá¯ááºááááºážá á¡ááŸááºááŸá¬ ááŒá±á¬ááºážáá²ááŸá¯áá»á¬ážá áá áºá áááºáá áºááá¯ááºážááᯠáá»áœááºá¯ááºááá¯á· áááŸáááá¯ááºááá·áº áááºážáááºážááŒáá·áº á¡ááŸá¬ážá¡ááœááºážáá áºáᯠááŒá áºáá±á«áºáá¬ááá¯ááºááẠ- á¡áá±á¬ááºážá¡áááºááŒá¯áá¯ááºááŒááºážá á¡ááºáááºáááºááŸá¯ ááŒá áºáá±á¬áºáááºáž á¡á±á¬áºááá±áá¬á¡á¬áž áá»áá¯ážáá±á¬ááºáá¶ááááºááŒá áºáááºá áá»áœááºá¯ááºááá¯á·áá¥ááá¬ááœááºáá²á·ááá¯á·á á¡á±á¬áºááá±áá¬ááẠá¡ááŸá¬ážá¡ááœááºážáááŒá áºáá® á á¬ááŒá±á¬ááºážáá áºááŒá±á¬ááºážááᯠá¡ááºááááºáá¯ááºááá¯ááºáá²á·áááº-
=> SELECT * FROM heap_page('t',0);
ctid | state | xmin | xmax | t_ctid
-------+--------+----------+-------+--------
(0,1) | normal | 3669 (c) | 3672 | (0,4)
(0,2) | normal | 3670 (a) | 0 (a) | (0,2)
(0,3) | normal | 3671 (c) | 0 (a) | (0,3)
(0,4) | normal | 3672 | 0 (a) | (0,4)
(4 rows)
psql ááœáẠááŸá¬ážááœááºážáá±á¬ á¡á±á¬áºááá±áá¬á áá¯ááºáá±á¬ááºáá»ááºáá»á¬ážááᯠááŒááºááŸáá·áºááœá¬ážááá²á·ááá¯á· áá»ááºááœááºááŒá®ážáá±á¬áẠááœá±áá±ážááœá±áá°ááᯠáááºáááºáá¯ááºáá±á¬ááºááá¯ááºá á±ááá·áº áá¯ááºáá áºáᯠááŸááááºáᯠááá¯ááá«áááºá
=> set ON_ERROR_ROLLBACK on
=> BEGIN;
=> SELECT * FROM t;
id | s
----+-----
2 | FOO
4 | BAR
(2 rows)
=> UPDATE t SET s = repeat('X', 1/(id-4));
ERROR: division by zero
=> SELECT * FROM t;
id | s
----+-----
2 | FOO
4 | BAR
(2 rows)
=> COMMIT;
á€áá¯ááºááœááºá psql ááẠcommand áá áºáá¯á á®áááŸá±á·ááœáẠááœááºááá¯ááºáá±á¬ save point ááᯠá¡ááŸááºáááẠáá¬ážááŸáááŒá±á¬ááºáž ááá·áºááŸááºážááẠááááºáá«áá²á áá¡á±á¬ááºááŒááºáá«á áááºážááᯠrollback áá¯ááºááẠá áááºáááºáá±ážááŸááºáá»á¬áž áááºááŸááºááŒááºáž (áááºážááá¯á·ááᯠáá±á¬ááºááŒá±á¬ááºážááŒááºáááŸáá·áºáá²) ááœáẠá¡áá±ážáá«áá±á¬ á¡áá¬áá»á¬áž áá«áááºáá±á¬ááŒá±á¬áá·áº á€áá¯ááºááᯠáá°áááºážá¡ááá¯ááºáž á¡áá¯á¶ážáááŒá¯áá«á
source: www.habr.com