MVCC-3ред рд╕реНрдЯреНрд░рд┐рдЩ рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВ

рддреНрдпрд╕реИрд▓реЗ, рд╣рд╛рдореАрд▓реЗ рд╕рдореНрдмрдиреНрдзрд┐рдд рдореБрджреНрджрд╛рд╣рд░реВ рд╡рд┐рдЪрд╛рд░ рдЧрд░реЗрдХрд╛ рдЫреМрдВ рдЗрдиреНрд╕реБрд▓реЗрд╢рди, рд░ рдХреЛ рдмрд╛рд░реЗ рдорд╛ рдПрдХ рд░рд┐рдЯреНрд░реАрдЯ рдЧрд░реЗ рдиреНрдпреВрди рд╕реНрддрд░рдорд╛ рдбрд╛рдЯрд╛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдЧрд░реНрджреИред рд░ рдЕрдиреНрддрдорд╛ рд╣рд╛рдореА рд╕рдмреИрднрдиреНрджрд╛ рд░реЛрдЪрдХ рднрд╛рдЧрдорд╛ рдкреБрдЧреНрдпреМрдВ - рд╕реНрдЯреНрд░рд┐рдЩ рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВред

рд╣реЗрдбрд░

рд╣рд╛рдореАрд▓реЗ рдкрд╣рд┐рд▓реЗ рдиреИ рднрдиреЗрдХрд╛ рдЫреМрдВ, рдкреНрд░рддреНрдпреЗрдХ рдкрдЩреНрдХреНрддрд┐ рдПрдХреИ рд╕рд╛рде рдбреЗрдЯрд╛рдмреЗрд╕рдорд╛ рдзреЗрд░реИ рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВрдорд╛ рдЕрд╡рд╕реНрдерд┐рдд рд╣реБрди рд╕рдХреНрдЫред рдПрдЙрдЯрд╛ рд╕рдВрд╕реНрдХрд░рдг рдХреБрдиреИ рди рдХреБрдиреИ рд░реВрдкрдорд╛ рдЕрд░реНрдХреЛрдмрд╛рдЯ рднрд┐рдиреНрди рд╣реБрдиреБрдкрд░реНрдЫред рдпрд╕ рдЙрджреНрджреЗрд╢реНрдпрдХрд╛ рд▓рд╛рдЧрд┐, рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрд╕реНрдХрд░рдгрдорд╛ рджреБрдИрд╡рдЯрд╛ рдЕрдВрдХрд╣рд░реВ рдЫрдиреН рдЬрд╕рд▓реЗ рдпрд╕ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ рдХрд╛рд░реНрдпрдХреЛ "рд╕рдордп" рдирд┐рд░реНрдзрд╛рд░рдг рдЧрд░реНрджрдЫ (xmin рд░ xmax)ред рдЙрджреНрдзрд░рдгрд╣рд░реВрдорд╛ - рдХрд┐рдирднрдиреЗ рдпреЛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ рд╕рдордп рд╣реЛрдЗрди, рддрд░ рд╡рд┐рд╢реЗрд╖ рдмрдвреНрджреЛ рдХрд╛рдЙрдиреНрдЯрд░ред рд░ рдпреЛ рдХрд╛рдЙрдиреНрдЯрд░ рд▓реЗрдирджреЗрди рдирдореНрдмрд░ рд╣реЛред

(рд╕рд╛рдорд╛рдиреНрдп рд░реВрдкрдорд╛, рд╡рд╛рд╕реНрддрд╡рд┐рдХрддрд╛ рдЭрдиреН рдЬрдЯрд┐рд▓ рдЫ: рдХрд╛рдЙрдиреНрдЯрд░рдХреЛ рд╕реАрдорд┐рдд рдмрд┐рдЯ рдХреНрд╖рдорддрд╛рдХреЛ рдХрд╛рд░рдг рд▓реЗрдирджреЗрди рдирдореНрдмрд░ рд╕рдзреИрдВ рдмрдвреНрди рд╕рдХреНрджреИрдиред рддрд░ рд╣рд╛рдореА рдлреНрд░рд┐рдЬрд┐рдЩрдорд╛ рдкреБрдЧреНрджрд╛ рдпреА рд╡рд┐рд╡рд░рдгрд╣рд░реВрд▓рд╛рдИ рд╡рд┐рд╕реНрддреГрдд рд░реВрдкрдорд╛ рд╣реЗрд░реНрдиреЗрдЫреМрдВред)

рдЬрдм рдкрдЩреНрдХреНрддрд┐ рдмрдирд╛рдЗрдиреНрдЫ, xmin рд▓рд╛рдИ INSERT рдЖрджреЗрд╢ рдЬрд╛рд░реА рдЧрд░реНрдиреЗ рд▓реЗрдирджреЗрди рдирдореНрдмрд░рдорд╛ рд╕реЗрдЯ рдЧрд░рд┐рдиреНрдЫ, рд░ xmax рдЦрд╛рд▓реА рдЫреЛрдбрд┐рдиреНрдЫред

рдЬрдм рдкрдЩреНрдХреНрддрд┐ рдореЗрдЯрд╛рдЗрдиреНрдЫ, рд╣рд╛рд▓рдХреЛ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ xmax рдорд╛рди DELETE рдкреНрд░рджрд░реНрд╢рди рдЧрд░реНрдиреЗ рд▓реЗрдирджреЗрдирдХреЛ рд╕рдВрдЦреНрдпрд╛рд╕рдБрдЧ рдЪрд┐рдиреНрд╣ рд▓рдЧрд╛рдЗрдиреНрдЫред

рдЬрдм рдкрдЩреНрдХреНрддрд┐ рдЕрдкрдбреЗрдЯ рдЖрджреЗрд╢рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рдорд╛рд░реНрдЬрди рдЧрд░рд┐рдиреНрдЫ, рджреБрдИ рдХрд╛рд░реНрдпрд╣рд░реВ рд╡рд╛рд╕реНрддрд╡рдорд╛ рдкреНрд░рджрд░реНрд╢рди рдЧрд░рд┐рдиреНрдЫ: DELETE рд░ INSERTред рдкрдЩреНрдХреНрддрд┐рдХреЛ рд╣рд╛рд▓рдХреЛ рд╕рдВрд╕реНрдХрд░рдгрд▓реЗ рдЕрджреНрдпрд╛рд╡рдзрд┐рдХ рдкреНрд░рджрд░реНрд╢рди рдЧрд░реЗрдХреЛ рд▓реЗрдирджреЗрдирдХреЛ рд╕рдВрдЦреНрдпрд╛ рдмрд░рд╛рдмрд░ xmax рд╕реЗрдЯ рдЧрд░реНрджрдЫред рдПрдЙрдЯреИ рд╕реНрдЯреНрд░рд┐рдЩрдХреЛ рдирдпрд╛рдБ рд╕рдВрд╕реНрдХрд░рдг рддреНрдпрд╕рдкрдЫрд┐ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░рд┐рдиреНрдЫ; рдпрд╕рдХреЛ xmin рдорд╛рди рдЕрдШрд┐рд▓реНрд▓реЛ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ xmax рдорд╛рдирд╕рдБрдЧ рдореЗрд▓ рдЦрд╛рдиреНрдЫред

xmin рд░ xmax рдХреНрд╖реЗрддреНрд░рд╣рд░реВ рдкрдЩреНрдХреНрддрд┐ рд╕рдВрд╕реНрдХрд░рдг рд╣реЗрдбрд░рдорд╛ рд╕рдорд╛рд╡реЗрд╢ рдЫрдиреНред рдпреА рдХреНрд╖реЗрддреНрд░рд╣рд░реВ рдмрд╛рд╣реЗрдХ, рд╣реЗрдбрд░рд▓реЗ рдЕрдиреНрдп рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫ, рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐:

  • infomask рдпрд╕ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ рдЧреБрдгрд╣рд░реВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЧрд░реНрдиреЗ рдмрд┐рдЯрд╣рд░реВрдХреЛ рд╢реНрд░реГрдВрдЦрд▓рд╛ рд╣реЛред рддрд┐рдиреАрд╣рд░реВрдордзреНрдпреЗ рдзреЗрд░реИ рдЫрдиреН; рд╣рд╛рдореА рдмрд┐рд╕реНрддрд╛рд░реИ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░ рдЧрд░реНрдиреЗрдЫреМрдВред
  • ctid рдЙрд╣реА рд▓рд╛рдЗрдирдХреЛ рдЕрд░реНрдХреЛ, рдирдпрд╛рдБ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ рд▓рд┐рдЩреНрдХ рд╣реЛред рд╕реНрдЯреНрд░рд┐рдЩрдХреЛ рд╕рдмреИрднрдиреНрджрд╛ рдирдпрд╛рдБ, рд╕рдмреИрднрдиреНрджрд╛ рд╣рд╛рд▓рдХреЛ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ рд▓рд╛рдЧрд┐, ctid рд▓реЗ рдпреЛ рд╕рдВрд╕реНрдХрд░рдгрд▓рд╛рдИ рдмреБрдЭрд╛рдЙрдБрдЫред рд╕рдВрдЦреНрдпрд╛рдорд╛ рдлрд╛рд░рдо (x,y) рдЫ, рдЬрд╣рд╛рдБ x рдкреГрд╖реНрда рдирдореНрдмрд░ рд╣реЛ, y array рдорд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдирдореНрдмрд░ рд╣реЛред
  • рдирд▓ рдмрд┐рдЯрдореНрдпрд╛рдк - рджрд┐рдЗрдПрдХреЛ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ рддреА рд╕реНрддрдореНрднрд╣рд░реВрд▓рд╛рдИ рдЪрд┐рдиреНрд╣ рд▓рдЧрд╛рдЙрдБрдЫ рдЬрд╕рдорд╛ рд╢реВрдиреНрдп рдорд╛рди (NULL) рд╣реБрдиреНрдЫред NULL рд╕рд╛рдорд╛рдиреНрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдорд╛рдирд╣рд░реВ рдордзреНрдпреЗ рдПрдХ рд╣реЛрдЗрди, рддреНрдпрд╕реИрд▓реЗ рд╡рд┐рд╢реЗрд╖рддрд╛ рдЕрд▓рдЧ рднрдгреНрдбрд╛рд░рдг рд╣реБрдиреБрдкрд░реНрдЫред

рдирддрд┐рдЬрд╛рдХреЛ рд░реВрдкрдорд╛, рд╣реЗрдбрд░ рдПрдХрджрдо рдареВрд▓реЛ рдЫ - рд░реЗрдЦрд╛рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ рд▓рд╛рдЧрд┐ рдХрдореНрддрд┐рдорд╛ 23 рдмрд╛рдЗрдЯрд╣рд░реВ, рд░ рд╕рд╛рдорд╛рдиреНрдпрддрдпрд╛ NULL рдмрд┐рдЯрдореНрдпрд╛рдкрдХреЛ рдХрд╛рд░рдгрд▓реЗ рдмрдвреАред рдпрджрд┐ рддрд╛рд▓рд┐рдХрд╛ "рд╕рд╛рдБрдШреБрд░реЛ" рдЫ (рдЕрд░реНрдерд╛рдд, рдХреЗрд╣рд┐ рд╕реНрддрдореНрднрд╣рд░реВ рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫ), рдУрднрд░рд╣реЗрдбрд▓реЗ рдЙрдкрдпреЛрдЧреА рдЬрд╛рдирдХрд╛рд░реА рднрдиреНрджрд╛ рдмрдвреА рд▓рд┐рди рд╕рдХреНрдЫред

рд╕рдореНрдорд┐рд▓рд┐рдд

рдирд┐рдореНрди-рд╕реНрддрд░ рд╕реНрдЯреНрд░рд┐рдЩ рдЕрдкрд░реЗрд╕рдирд╣рд░реВ рдХрд╕рд░реА рдкреНрд░рджрд░реНрд╢рди рдЧрд░рд┐рдиреНрдЫрдиреН рднрдиреНрдиреЗ рдмрд╛рд░реЗ рдирдЬрд┐рдХрдмрд╛рдЯ рд╣реЗрд░реМрдВ, рд╕рдореНрдорд┐рд▓рдирдмрд╛рдЯ рд╕реБрд░реБ рдЧрд░реНрдиреБрд╣реЛрд╕реНред

рдкреНрд░рдпреЛрдЧрд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐, рджреБрдИ рд╕реНрддрдореНрднрд╣рд░реВ рд░ рддрд┐рдиреАрд╣рд░реВрдордзреНрдпреЗ рдПрдЙрдЯрд╛рдорд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рдХреЛ рд╕рд╛рде рдирдпрд╛рдБ рддрд╛рд▓рд┐рдХрд╛ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реМрдВ:

=> 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 рдПрдХреНрд╕реНрдЯреЗрдиреНрд╕рдирдХреЛ heap_page_items рдкреНрд░рдХрд╛рд░реНрдпрд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ рд╕реВрдЪрдХ рд░ рдкрдЩреНрдХреНрддрд┐ рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВрдХреЛ рдмрд╛рд░реЗрдорд╛ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫ:

=> 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 рдорд╛ рд╣рд┐рдк рд╢рдмреНрджрд▓реЗ рддрд╛рд▓рд┐рдХрд╛рд╣рд░реВрд▓рд╛рдИ рдЬрдирд╛рдЙрдБрдЫред рдпреЛ рд╢рдмреНрджрдХреЛ рдЕрд░реНрдХреЛ рдЕрдиреМрдареЛ рдкреНрд░рдпреЛрдЧ рд╣реЛ - рдПрдХ рдвреЗрд░ рдЬреНрдЮрд╛рдд рдЫ рдбрд╛рдЯрд╛ рд╕рдВрд░рдЪрдирд╛, рдЬрд╕рдХреЛ рддрд╛рд▓рд┐рдХрд╛рд╕рдБрдЧ рдХреЗрд╣реА рдорд┐рд▓реНрджреИрдиред рдпрд╣рд╛рдБ рд╢рдмреНрдж "рд╕рдмреИ рдХреБрд░рд╛ рд╕рдБрдЧреИ рдлреНрдпрд╛рдБрдХрд┐рдПрдХреЛ рдЫ" рдХреЛ рдЕрд░реНрдердорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХреЛ рдЫ, рдЕрд░реНрдбрд░ рдЧрд░рд┐рдПрдХреЛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рдХреЛ рд╡рд┐рдкрд░рд┐рддред

рдкреНрд░рдХрд╛рд░реНрдпрд▓реЗ рдбреЗрдЯрд╛ "рдЬрд╕реНрддреЛ рдЫ" рджреЗрдЦрд╛рдЙрдБрдЫ, рдмреБрдЭреНрди рдЧрд╛рд╣реНрд░реЛ рднрдПрдХреЛ рдврд╛рдБрдЪрд╛рдорд╛ред рдпрд╕рд▓рд╛рдИ рдкрддреНрддрд╛ рд▓рдЧрд╛рдЙрди, рд╣рд╛рдореА рдЬрд╛рдирдХрд╛рд░реАрдХреЛ рдЕрдВрд╢ рдорд╛рддреНрд░ рдЫреЛрдбреНрдиреЗрдЫреМрдВ рд░ рдпрд╕рд▓рд╛рдИ рдмреБрдЭреНрдиреЗ рдЫреМрдВ:

=> 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 рд╕реВрдЪрдХрдХреЛ рдЕрд╡рд╕реНрдерд╛ рдмреБрдЭрд┐рдпреЛред рдпрд╣рд╛рдБ рдпреЛ "рд╕рд╛рдорд╛рдиреНрдп" рд╣реЛ - рдпрд╕рдХреЛ рдорддрд▓рдм рдпреЛ рд╣реЛ рдХрд┐ рд╕реВрдЪрдХрд▓реЗ рд╡рд╛рд╕реНрддрд╡рдорд╛ рд╕реНрдЯреНрд░рд┐рдЩрдХреЛ рд╕рдВрд╕реНрдХрд░рдгрд▓рд╛рдИ рдЬрдирд╛рдЙрдБрдЫред рд╣рд╛рдореА рдкрдЫрд┐ рдЕрдиреНрдп рдЕрд░реНрдерд╣рд░реВ рд╣реЗрд░реНрдиреЗрдЫреМрдВред
  • рд╕рдмреИ рдЬрд╛рдирдХрд╛рд░реА рдмрд┐рдЯрд╣рд░реВ рдордзреНрдпреЗ, рдЕрд╣рд┐рд▓реЗрд╕рдореНрдо рджреБрдИ рдЬреЛрдбреА рдорд╛рддреНрд░ рдкрд╣рд┐рдЪрд╛рди рдЧрд░рд┐рдПрдХреЛ рдЫред xmin_committed рд░ xmin_aborted рдмрд┐рдЯрд╣рд░реВрд▓реЗ рд▓реЗрдирджреЗрди рдирдореНрдмрд░ xmin рдкреНрд░рддрд┐рдмрджреНрдз рдЫ рдХрд┐ рдЫреИрди рднрдиреЗрд░ рд╕рдВрдХреЗрдд рдЧрд░реНрджрдЫ (рдЕрдмрд░реНрдЯ рдЧрд░рд┐рдПрдХреЛ)ред рджреБрдИ рд╕рдорд╛рди рдмрд┐рдЯреНрд╕ рд▓реЗрдирджреЗрди рдирдореНрдмрд░ xmax рд▓рд╛рдИ рдмреБрдЭрд╛рдЙрдБрдЫред

рд╣рд╛рдореА рдХреЗ рджреЗрдЦреНрдЫреМрдВ? рдЬрдм рддрдкрд╛рдЗрдБ рдкрдЩреНрдХреНрддрд┐ рд╕рдореНрдорд┐рд▓рд┐рдд рдЧрд░реНрдиреБрд╣реБрдиреНрдЫ, рддрд╛рд▓рд┐рдХрд╛ рдкреГрд╖реНрдардорд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдирдореНрдмрд░ 1 рджреЗрдЦрд╛ рдкрд░реНрдиреЗрдЫ, рдкрдЩреНрдХреНрддрд┐рдХреЛ рдкрд╣рд┐рд▓реЛ рд░ рдПрдХрдорд╛рддреНрд░ рд╕рдВрд╕реНрдХрд░рдгрд▓рд╛рдИ рд╕рдВрдХреЗрдд рдЧрд░реНрджреИред

рд╕реНрдЯреНрд░рд┐рдЩ рд╕рдВрд╕реНрдХрд░рдгрдорд╛, xmin рдлрд┐рд▓реНрдб рд╣рд╛рд▓рдХреЛ рд▓реЗрдирджреЗрди рдирдореНрдмрд░рд▓реЗ рднрд░рд┐рдПрдХреЛ рдЫред рд▓реЗрдирджреЗрди рдЕрдЭреИ рд╕рдХреНрд░рд┐рдп рдЫ, рддреНрдпрд╕реИрд▓реЗ рджреБрдмреИ xmin_committed рд░ xmin_aborted рдмрд┐рдЯрд╣рд░реВ рд╕реЗрдЯ рдЧрд░рд┐рдПрдХрд╛ рдЫреИрдирдиреНред

рдкрдЩреНрдХреНрддрд┐ рд╕рдВрд╕реНрдХрд░рдг ctid рдлрд┐рд▓реНрдбрд▓реЗ рдЙрд╣реА рдкрдЩреНрдХреНрддрд┐рд▓рд╛рдИ рдЬрдирд╛рдЙрдБрдЫред рдпрд╕рдХреЛ рдорддрд▓рдм рдирдпрд╛рдБ рд╕рдВрд╕реНрдХрд░рдг рдЕрд╡рд╕реНрдерд┐рдд рдЫреИрдиред

xmax рдлрд┐рд▓реНрдб рдбрдореА рдирдореНрдмрд░ реж рд▓реЗ рднрд░рд┐рдПрдХреЛ рдЫ рдХрд┐рдирднрдиреЗ рдкрдЩреНрдХреНрддрд┐рдХреЛ рдпреЛ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдЯрд╛рдЗрдПрдХреЛ рдЫреИрди рд░ рд╣рд╛рд▓рдХреЛ рдЫред рд▓реЗрдирджреЗрдирд▓реЗ рдпреЛ рдирдореНрдмрд░рдорд╛ рдзреНрдпрд╛рди рджрд┐рдиреЗрдЫреИрди рдХрд┐рдирднрдиреЗ xmax_aborted рдмрд┐рдЯ рд╕реЗрдЯ рдЧрд░рд┐рдПрдХреЛ рдЫред

рд▓реЗрдирджреЗрди рдирдореНрдмрд░рд╣рд░реВрдорд╛ рдЬрд╛рдирдХрд╛рд░реА рдмрд┐рдЯрд╣рд░реВ рдердкреЗрд░ рдкрдардиреАрдпрддрд╛ рд╕реБрдзрд╛рд░ рдЧрд░реНрдиреЗ рджрд┐рд╢рд╛рдорд╛ рдердк рдПрдХ рдХрджрдо рдЪрд╛рд▓реМрдВред рд░ рдПрдЙрдЯрд╛ рдкреНрд░рдХрд╛рд░реНрдп рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реМрдВ, рдХрд┐рдирдХрд┐ рд╣рд╛рдореАрд▓рд╛рдИ рдПрдХ рдкрдЯрдХ рднрдиреНрджрд╛ рдмрдвреА рдЕрдиреБрд░реЛрдз рдЪрд╛рд╣рд┐рдиреНрдЫ:

=> 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)

рд╕рдорд╛рди, рддрд░ рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдХрдо рд╡рд┐рд╕реНрддреГрдд, рдЬрд╛рдирдХрд╛рд░реА рддрд╛рд▓рд┐рдХрд╛рдмрд╛рдЯ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ, рдЫрджреНрдо-рд╕реНрддрдореНрднрд╣рд░реВ xmin рд░ xmax рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░:

=> SELECT xmin, xmax, * FROM t;
 xmin | xmax | id |  s  
------+------+----+-----
 3664 |    0 |  1 | FOO
(1 row)

рдлрд┐рдХреНрд╕реЗрд╢рди

рдпрджрд┐ рд▓реЗрдирджреЗрди рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕рдореНрдкрдиреНрди рднрдпреЛ рднрдиреЗ, рддрдкрд╛рдИрдВрд▓реЗ рдпрд╕рдХреЛ рд╕реНрдерд┐рддрд┐ рд╕рдореНрдЭрдиреБ рдЖрд╡рд╢реНрдпрдХ рдЫ - рдпреЛ рдкреНрд░рддрд┐рдмрджреНрдз рдЫ рднрдиреЗрд░ рдзреНрдпрд╛рди рджрд┐рдиреБрд╣реЛрд╕реНред рдпреЛ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐, XACT рднрдирд┐рдиреЗ рд╕рдВрд░рдЪрдирд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдиреНрдЫ (рд░ рд╕рдВрд╕реНрдХрд░рдг 10 рднрдиреНрджрд╛ рдкрд╣рд┐рд▓реЗ рдпрд╕рд▓рд╛рдИ CLOG (рдХрдорд┐рдЯ рд▓рдЧ) рднрдирд┐рдиреНрдереНрдпреЛ рд░ рдпреЛ рдирд╛рдо рдЕрдЭреИ рдкрдирд┐ рд╡рд┐рднрд┐рдиреНрди рдард╛рдЙрдБрд╣рд░реВрдорд╛ рдлреЗрд▓рд╛ рдкрд╛рд░реНрди рд╕рдХрд┐рдиреНрдЫ)ред

XACT рдкреНрд░рдгрд╛рд▓реА рд╕реВрдЪреА рддрд╛рд▓рд┐рдХрд╛ рд╣реЛрдЗрди; рдпреА PGDATA/pg_xact рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реАрдорд╛ рд░рд╣реЗрдХрд╛ рдлрд╛рдЗрд▓рд╣рд░реВ рд╣реБрдиреНред рддрд┐рдиреАрд╣рд░реВрд╕рдБрдЧ рдкреНрд░рддреНрдпреЗрдХ рд▓реЗрдирджреЗрдирдХреЛ рд▓рд╛рдЧрд┐ рджреБрдИ рдмрд┐рдЯрд╣рд░реВ рдЫрдиреН: рдкреНрд░рддрд┐рдмрджреНрдз рд░ рд░рджреНрдж рдЧрд░рд┐рдПрдХреЛ - рдкрдЩреНрдХреНрддрд┐ рд╕рдВрд╕реНрдХрд░рдг рд╣реЗрдбрд░рдорд╛ рдЬрд╕реНрддреИред рдпреЛ рдЬрд╛рдирдХрд╛рд░реА рдХреЗрд╡рд▓ рд╕реБрд╡рд┐рдзрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдзреЗрд░реИ рдлрд╛рдЗрд▓рд╣рд░реВрдорд╛ рд╡рд┐рднрд╛рдЬрд┐рдд рдЧрд░рд┐рдПрдХреЛ рдЫ; рд╣рд╛рдореА рдлреНрд░рд┐рдЬрд┐рдЩ рд╡рд┐рдЪрд╛рд░ рдЧрд░реНрджрд╛ рд╣рд╛рдореА рдпрд╕ рдореБрджреНрджрд╛рдорд╛ рдлрд░реНрдХрдиреЗрдЫреМрдВред рд░ рдпреА рдлрд╛рдЗрд▓рд╣рд░реВрд╕рдБрдЧ рдХрд╛рдо рдкреГрд╖реНрда рдкреГрд╖реНрдардорд╛ рдЧрд░рд┐рдиреНрдЫ, рдЕрд░реВ рд╕рдмреИрд╕рдБрдЧ рдЬрд╕реНрддреИред

рддреНрдпрд╕реЛрднрдП, рдЬрдм XACT рдорд╛ рдПрдХ рд▓реЗрдирджреЗрди рдкреНрд░рддрд┐рдмрджреНрдз рд╣реБрдиреНрдЫ, рдпреЛ рд▓реЗрдирджреЗрдирдХреЛ рд▓рд╛рдЧрд┐ рдкреНрд░рддрд┐рдмрджреНрдз рдмрд┐рдЯ рд╕реЗрдЯ рдЧрд░рд┐рдиреНрдЫред рд░ рдпреЛ рд╕рдмреИ рдХрдорд┐рдЯрд┐рдЩ рд╕рдордпрдорд╛ рд╣реБрдиреНрдЫ (рдпрджреНрдпрдкрд┐ рд╣рд╛рдореА рдЕрдЭреИ рдкреНрд░рд┐-рд░реЗрдХрд░реНрдбрд┐рдЩ рд▓рдЧ рдмрд╛рд░реЗ рдХреБрд░рд╛ рдЧрд░реНрджреИрдиреМрдВ)ред

рдЬрдм рдЕрд░реНрдХреЛ рд▓реЗрдирджреЗрдирд▓реЗ рд╣рд╛рдореАрд▓реЗ рднрд░реНрдЦрд░реИ рд╣реЗрд░реЗрдХреЛ рддрд╛рд▓рд┐рдХрд╛ рдкреГрд╖реНрдардорд╛ рдкрд╣реБрдБрдЪ рдЧрд░реНрдЫ, рдпрд╕рд▓реЗ рдзреЗрд░реИ рдкреНрд░рд╢реНрдирд╣рд░реВрдХреЛ рдЬрд╡рд╛рдл рджрд┐рдиреБ рдкрд░реНрдЫред

  1. рдХреЗ xmin рд▓реЗрдирджреЗрди рдкреВрд░рд╛ рднрдпреЛ? рдпрджрд┐ рд╣реЛрдЗрди рднрдиреЗ, рддрдм рд╕реНрдЯреНрд░рд┐рдЩрдХреЛ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░рд┐рдПрдХреЛ рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦрд┐рдиреБ рд╣реБрдБрджреИрдиред
    рдпреЛ рдЬрд╛рдБрдЪ рдЕрд░реНрдХреЛ рд╕рдВрд░рдЪрдирд╛ рд╣реЗрд░реЗрд░ рдЧрд░рд┐рдиреНрдЫ, рдЬреБрди рдЙрджрд╛рд╣рд░рдгрдХреЛ рд╕рд╛рдЭрд╛ рдореЗрдореЛрд░реАрдорд╛ рдЕрд╡рд╕реНрдерд┐рдд рдЫ рд░ ProcArray рднрдирд┐рдиреНрдЫред рдпрд╕рд▓реЗ рд╕рдмреИ рд╕рдХреНрд░рд┐рдп рдкреНрд░рдХреНрд░рд┐рдпрд╛рд╣рд░реВрдХреЛ рд╕реВрдЪреА рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫ, рд░ рдкреНрд░рддреНрдпреЗрдХрдХреЛ рд▓рд╛рдЧрд┐ рдпрд╕рдХреЛ рд╣рд╛рд▓рдХреЛ (рд╕рдХреНрд░рд┐рдп) рд▓реЗрдирджреЗрдирдХреЛ рд╕рдВрдЦреНрдпрд╛ рд╕рдВрдХреЗрдд рдЧрд░рд┐рдПрдХреЛ рдЫред
  2. рдпрджрд┐ рдкреВрд░рд╛ рднрдпреЛ рднрдиреЗ, рдХрд╕рд░реА - рдХрдорд┐рдЯ рд╡рд╛ рд░рджреНрдж рдЧрд░реЗрд░? рдпрджрд┐ рд░рджреНрдж рдЧрд░рд┐рдпреЛ рднрдиреЗ, рдкрдЩреНрдХреНрддрд┐ рд╕рдВрд╕реНрдХрд░рдг рдкрдирд┐ рджреЗрдЦрд┐рдиреБ рд╣реБрдБрджреИрдиред
    рдпреЛ рд╡рд╛рд╕реНрддрд╡рдорд╛ XACT рдХреЛ рд▓рд╛рдЧрд┐ рд╣реЛред рддрд░, рдпрджреНрдпрдкрд┐ XACT рдХреЛ рдЕрдиреНрддрд┐рдо рдкреГрд╖реНрдард╣рд░реВ RAM рдорд╛ рдмрдлрд░рд╣рд░реВрдорд╛ рднрдгреНрдбрд╛рд░ рдЧрд░рд┐рдПрдХреЛ рдЫ, рдпреЛ рдЕрдЭреИ рдкрдирд┐ рдкреНрд░рддреНрдпреЗрдХ рдкрдЯрдХ XACT рдЬрд╛рдБрдЪ рдЧрд░реНрди рдорд╣рдБрдЧреЛ рдЫред рддреНрдпрд╕реИрд▓реЗ, рд▓реЗрдирджреЗрди рд╕реНрдерд┐рддрд┐ рдирд┐рд░реНрдзрд╛рд░рдг рднрдПрдкрдЫрд┐, рдпреЛ рд╕реНрдЯреНрд░рд┐рдЩ рд╕рдВрд╕реНрдХрд░рдгрдХреЛ xmin_committed рд░ xmin_aborted рдмрд┐рдЯреНрд╕рдорд╛ рд▓реЗрдЦрд┐рдиреНрдЫред рдпрджрд┐ рдпреА рдордзреНрдпреЗ рдХреБрдиреИ рдПрдХ рдмрд┐рдЯ рд╕реЗрдЯ рдЧрд░рд┐рдПрдХреЛ рдЫ рднрдиреЗ, рд▓реЗрдирджреЗрдирдХреЛ рд╕реНрдерд┐рддрд┐ xmin рдЬреНрдЮрд╛рдд рдорд╛рдирд┐рдиреНрдЫ рд░ рдЕрд░реНрдХреЛ рд▓реЗрдирджреЗрдирд▓реЗ XACT рдкрд╣реБрдБрдЪ рдЧрд░реНрдиреБ рдкрд░реНрджреИрдиред

рдХрд┐рди рдпреА рдмрд┐рдЯреНрд╕ рд▓реЗрдирджреЗрди рдЖрдлреИрдВрд▓реЗ рд╕рдореНрдорд┐рд▓рд┐рдд рдЧрд░реНрджреИрдирдиреН? рдЬрдм рд╕рдореНрдорд┐рд▓рд┐рдд рд╣реБрдиреНрдЫ, рд▓реЗрдирджреЗрди рд╕рдлрд▓ рд╣реБрдиреНрдЫ рдХрд┐ рдЫреИрди рдерд╛рд╣рд╛ рдЫреИрдиред рд░ рдкреНрд░рддрд┐рдмрджреНрдзрддрд╛рдХреЛ рдХреНрд╖рдгрдорд╛, рдпреЛ рдЕрдм рд╕реНрдкрд╖реНрдЯ рдЫреИрди рдХреБрди рд▓рд╛рдЗрдирд╣рд░реВрдорд╛ рдХреБрди рдкреГрд╖реНрдард╣рд░реВ рдкрд░рд┐рд╡рд░реНрддрди рдЧрд░рд┐рдпреЛред рддреНрдпрд╣рд╛рдБ рддреНрдпрд╕реНрддрд╛ рдкреГрд╖реНрдард╣рд░реВ рдзреЗрд░реИ рд╣реБрди рд╕рдХреНрдЫрдиреН, рд░ рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рд╕рдореНрдЭрдирд╛ рд▓рд╛рднрджрд╛рдпрдХ рдЫреИрдиред рдердк рд░реВрдкрдорд╛, рдХреЗрд╣реА рдкреГрд╖реНрдард╣рд░реВ рдмрдлрд░ рдХреНрдпрд╛рд╕рдмрд╛рдЯ рдбрд┐рд╕реНрдХрдорд╛ рд╣рдЯрд╛рдЙрди рд╕рдХрд┐рдиреНрдЫ; рдмрд┐рдЯреНрд╕ рдкрд░рд┐рд╡рд░реНрддрди рдЧрд░реНрди рддрд┐рдиреАрд╣рд░реВрд▓рд╛рдИ рдкреБрди: рдкрдвреНрдирд╛рд▓реЗ рдХрдорд┐рдЯрд▓рд╛рдИ рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдврд┐рд▓реЛ рдЧрд░реНрдиреЗрдЫред

рдмрдЪрддрдХреЛ рдирдХрд╛рд░рд╛рддреНрдордХ рдкрдХреНрд╖ рдпреЛ рд╣реЛ рдХрд┐ рдкрд░рд┐рд╡рд░реНрддрди рдкрдЫрд┐, рдХреБрдиреИ рдкрдирд┐ рд▓реЗрдирджреЗрди (рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкрдвреНрдиреЗ рдкреНрд░рджрд░реНрд╢рди - 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 рд▓реЗрдирджреЗрди рд╕реНрдерд┐рддрд┐ рдирд┐рд░реНрдзрд╛рд░рдг рдЧрд░реНрдиреБрдкрд░реНрдиреЗрдЫ рд░ рдпрд╕рд▓рд╛рдИ рдЬрд╛рдирдХрд╛рд░реА рдмрд┐рдЯреНрд╕рдорд╛ рд▓реЗрдЦреНрдиреБрдкрд░реНрдЫ:

=> 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 рдмрд┐рдЯ рдЦрд╛рд▓реА рд╣реБрдиреНрдЫред

рдзреНрдпрд╛рди рджрд┐рдиреБрд╣реЛрд╕реН рдХрд┐ рд╕рдХреНрд░рд┐рдп рд▓реЗрдирджреЗрдирд╕рдБрдЧ рд╕рдореНрдмрдиреНрдзрд┐рдд xmax рдХреЛ рд╕реЗрдЯ рдорд╛рди рдкрдЩреНрдХреНрддрд┐ рд▓рдХрдХреЛ рд░реВрдкрдорд╛ рдХрд╛рд░реНрдп рдЧрд░реНрджрдЫред рдпрджрд┐ рдЕрд░реНрдХреЛ рд▓реЗрдирджреЗрдирд▓реЗ рдпреЛ рдкрдЩреНрдХреНрддрд┐ рдЕрджреНрдпрд╛рд╡рдзрд┐рдХ рдЧрд░реНрди рд╡рд╛ рдореЗрдЯрд╛рдЙрди рдЪрд╛рд╣рдиреНрдЫ рднрдиреЗ, рдпреЛ рд▓реЗрдирджреЗрди xmax рдкреВрд░рд╛ рд╣реБрдирдХреЛ рд▓рд╛рдЧрд┐ рдкрд░реНрдЦрди рдмрд╛рдзреНрдп рд╣реБрдиреЗрдЫред рд╣рд╛рдореА рдкрдЫрд┐ рдЕрд╡рд░реБрджреНрдз рдмрд╛рд░реЗ рдердк рдХреБрд░рд╛ рдЧрд░реНрдиреЗрдЫреМрдВред рдЕрд╣рд┐рд▓реЗрдХреЛ рд▓рд╛рдЧрд┐, рд╣рд╛рдореА рдкрдЩреНрдХреНрддрд┐ рд▓рдХрд╣рд░реВрдХреЛ рд╕рдВрдЦреНрдпрд╛ рдЕрд╕реАрдорд┐рдд рдЫ рднрдиреЗрд░ рдзреНрдпрд╛рди рджрд┐рдиреНрдЫреМрдВред рддрд┐рдиреАрд╣рд░реВрд▓реЗ RAM рдорд╛ рдард╛рдЙрдБ рд▓рд┐рди рд╕рдХреНрджреИрдирдиреН рд░ рдкреНрд░рдгрд╛рд▓реА рдкреНрд░рджрд░реНрд╢рди рддрд┐рдиреАрд╣рд░реВрдХреЛ рд╕рдВрдЦреНрдпрд╛ рдЧреНрд░рд╕реНрдд рдЫреИрдиред рд╕рд╛рдБрдЪреЛ, "рд▓рд╛рдореЛ" рд▓реЗрдирджреЗрдирдХрд╛ рдЕрдиреНрдп рдмреЗрдлрд╛рдЗрджрд╛рд╣рд░реВ рдЫрдиреН, рддрд░ рдкрдЫрд┐ рдердкред

рд▓рд╛рдЗрди рдореЗрдЯреМрдВред

=> BEGIN;
=> DELETE FROM t;
=> SELECT txid_current();
 txid_current 
--------------
         3665
(1 row)

рд╣рд╛рдореАрд▓реЗ рджреЗрдЦреНрдпреМрдВ рдХрд┐ рд▓реЗрдирджреЗрди рдирдореНрдмрд░ xmax рдлрд┐рд▓реНрдбрдорд╛ рд▓реЗрдЦрд┐рдПрдХреЛ рдЫ, рддрд░ рдЬрд╛рдирдХрд╛рд░реА рдмрд┐рдЯрд╣рд░реВ рд╕реЗрдЯ рдЧрд░рд┐рдПрдХреЛ рдЫреИрди:

=> 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)

рдЕрджреНрдпрд╛рд╡рдзрд┐рдХ рдЧрд░реНрдиреБрд╣реЛрд╕реН

рдЕрджреНрдпрд╛рд╡рдзрд┐рдХрд▓реЗ рдкрд╣рд┐рд▓реЗ рдкрдЩреНрдХреНрддрд┐рдХреЛ рд╣рд╛рд▓рдХреЛ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдЯрд╛рдПрдХреЛ рд░ рддреНрдпрд╕рдкрдЫрд┐ рдирдпрд╛рдБ рд╕рдореНрдорд┐рд▓рд┐рдд рдЧрд░реЗ рдЬрд╕реНрддреИ рдХрд╛рдо рдЧрд░реНрджрдЫред

=> 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 рдмрд┐рдЯ рдЦрд╛рд▓реА рдЧрд░рд┐рдПрдХреЛ рдЫ рдХрд┐рдирднрдиреЗ рд╣рд╛рд▓рдХреЛ рдХрд╛рд░реЛрдмрд╛рд░рдХреЛ рд╕реНрдерд┐рддрд┐ рдЕрдЭреИ рдерд╛рд╣рд╛ рдЫреИрдиред

рд▓рд╛рдЗрдирдХреЛ рдкрд╣рд┐рд▓реЛ рд╕рдВрд╕реНрдХрд░рдгрд▓реЗ рдЕрдм рджреЛрд╕реНрд░реЛ (t_ctid рдлрд┐рд▓реНрдб) рд▓рд╛рдИ рдирдпрд╛рдБрдХреЛ рд░реВрдкрдорд╛ рдмреБрдЭрд╛рдЙрдБрдЫред

рджреЛрд╕реНрд░реЛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдкреГрд╖реНрдардорд╛ рджреЗрдЦрд╛ рдкрд░реНрджрдЫ рд░ рджреЛрд╕реНрд░реЛ рдкрдЩреНрдХреНрддрд┐рд▓реЗ рддрд╛рд▓рд┐рдХрд╛ рдкреГрд╖реНрдардорд╛ рджреЛрд╕реНрд░реЛ рд╕рдВрд╕реНрдХрд░рдгрд▓рд╛рдИ рд╕рдиреНрджрд░реНрдн рдЧрд░реНрджрдЫред

рдореЗрдЯрд╛рдЙрдиреЗ рдХреНрд░рдордорд╛ рдЬрд╕реНрддреИ, рдкрдЩреНрдХреНрддрд┐рдХреЛ рдкрд╣рд┐рд▓реЛ рд╕рдВрд╕реНрдХрд░рдгрдорд╛ xmax рдорд╛рди рдкрдЩреНрдХреНрддрд┐ рд▓рдХ рднрдПрдХреЛ рд╕рдВрдХреЗрдд рд╣реЛред

рдЦреИрд░, рд▓реЗрдирджреЗрди рдкреВрд░рд╛ рдЧрд░реМрдВред

=> COMMIT;

рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛

рдЕрд╣рд┐рд▓реЗрд╕рдореНрдо рд╣рд╛рдореАрд▓реЗ рдЯреЗрдмрд▓рдХрд╛ рдкрд╛рдирд╛рд╣рд░реВрдХреЛ рдмрд╛рд░реЗрдорд╛ рдорд╛рддреНрд░ рдХреБрд░рд╛ рдЧрд░реЗрдХрд╛ рдЫреМрдВред рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рднрд┐рддреНрд░ рдХреЗ рд╣реБрдиреНрдЫ?

рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдкреГрд╖реНрдард╣рд░реВрдорд╛ рдЬрд╛рдирдХрд╛рд░реА рд╕реВрдЪрдХрд╛рдВрдХрдХреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░рдХреЛ рдЖрдзрд╛рд░рдорд╛ рдзреЗрд░реИ рдлрд░рдХ рд╣реБрдиреНрдЫред рд░ рдПрдХ рдкреНрд░рдХрд╛рд░рдХреЛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рдорд╛ рдкрдирд┐ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░рдХрд╛ рдкреГрд╖реНрдард╣рд░реВ рдЫрдиреНред рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, B-рдЯреНрд░реАрдорд╛ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдкреГрд╖реНрда рд░ "рдирд┐рдпрдорд┐рдд" рдкреГрд╖реНрдард╣рд░реВ рдЫрдиреНред

рдпрджреНрдпрдкрд┐, рдкреГрд╖реНрдардорд╛ рдкреНрд░рд╛рдп: рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рд░ рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рдЖрдлреИрдВрдорд╛ рдкреЛрдЗрдиреНрдЯрд░реНрд╕рдХреЛ рдПрд░реНрд░реЗ рд╣реБрдиреНрдЫ (рдЯреЗрдмрд▓ рдкреГрд╖реНрда рдЬрд╕реНрддреИ)ред рдердк рд░реВрдкрдорд╛, рдкреГрд╖реНрдардХреЛ рдЕрдиреНрддреНрдпрдорд╛ рд╡рд┐рд╢реЗрд╖ рдбрд╛рдЯрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдард╛рдЙрдБ рдЫред

рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рдорд╛ рдкрдЩреНрдХреНрддрд┐рд╣рд░реВ рдкрдирд┐ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛рдХреЛ рдкреНрд░рдХрд╛рд░рдХреЛ рдЖрдзрд╛рд░рдорд╛ рдзреЗрд░реИ рдлрд░рдХ рд╕рдВрд░рдЪрдирд╛рд╣рд░реВ рд╣реБрди рд╕рдХреНрдЫрдиреНред рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдмреА-рдЯреНрд░реАрдХреЛ рд▓рд╛рдЧрд┐, рдкрд╛рдд рдкреГрд╖реНрдард╣рд░реВрд╕рдБрдЧ рд╕рдореНрдмрдиреНрдзрд┐рдд рдкрдЩреНрдХреНрддрд┐рд╣рд░реВрдорд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреБрдЮреНрдЬреА рдорд╛рди рд░ рд╕рдореНрдмрдиреНрдзрд┐рдд рддрд╛рд▓рд┐рдХрд╛ рдкрдЩреНрдХреНрддрд┐рдХреЛ рд╕рдиреНрджрд░реНрдн (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 рд▓реЗ рдЕрдиреБрдХреВрд▓рди рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрдЫ рдЬрд╕рд▓реЗ рдпрд╕рд▓рд╛рдИ рд▓реЗрдирджреЗрди рдирдореНрдмрд░рд╣рд░реВ "рдмрдЪрдд" рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫред

рдпрджрд┐ рд▓реЗрдирджреЗрдирд▓реЗ рдбреЗрдЯрд╛ рдорд╛рддреНрд░ рдкрдвреНрдЫ рднрдиреЗ, рдпрд╕рд▓реЗ рдкрдЩреНрдХреНрддрд┐ рд╕рдВрд╕реНрдХрд░рдгрд╣рд░реВрдХреЛ рджреГрд╢реНрдпрддрд╛рдорд╛ рдХреБрдиреИ рдкреНрд░рднрд╛рд╡ рдкрд╛рд░реНрджреИрдиред рддреНрдпрд╕рдХрд╛рд░рдг, рд╕реЗрд╡рд╛ рдкреНрд░рдХреНрд░рд┐рдпрд╛рд▓реЗ рдкрд╣рд┐рд▓реЗ рд▓реЗрдирджреЗрдирдорд╛ рднрд░реНрдЪреБрдЕрд▓ xid рдЬрд╛рд░реА рдЧрд░реНрдЫред рд╕рдВрдЦреНрдпрд╛ рдПрдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЖрдИрдбреА рд░ рдПрдХ рдЕрдиреБрдХреНрд░рдо рд╕рдВрдЦреНрдпрд╛ рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫред

рдпреЛ рдирдореНрдмрд░ рдЬрд╛рд░реА рдЧрд░реНрди рд╕рдмреИ рдкреНрд░рдХреНрд░рд┐рдпрд╛рд╣рд░реВ рдмреАрдЪ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬреЗрд╕рди рдЖрд╡рд╢реНрдпрдХ рдЫреИрди рд░ рддреНрдпрд╕реИрд▓реЗ рдзреЗрд░реИ рдЫрд┐рдЯреЛ рдЫред рд╣рд╛рдореА рдлреНрд░рд┐рдЬрд┐рдЩрдХреЛ рдмрд╛рд░реЗрдорд╛ рдХреБрд░рд╛ рдЧрд░реНрджрд╛ рднрд░реНрдЪреБрдЕрд▓ рдирдореНрдмрд░рд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗ рдЕрд░реНрдХреЛ рдХрд╛рд░рдгрд╕рдБрдЧ рдкрд░рд┐рдЪрд┐рдд рд╣реБрдиреЗрдЫреМрдВред

рдбрд╛рдЯрд╛ рд╕реНрдиреНрдпрд╛рдкрд╕рдЯрд╣рд░реВрдорд╛ рднрд░реНрдЪреБрдЕрд▓ рдирдореНрдмрд░рд╣рд░реВ рдХреБрдиреИ рдкрдирд┐ рд╣рд┐рд╕рд╛рдмрд▓реЗ рд▓рд┐рдЗрдБрджреИрдиред

рд╕рдордпрдХреЛ рд╡рд┐рднрд┐рдиреНрди рдмрд┐рдиреНрджреБрд╣рд░реВрдорд╛, рдкреНрд░рдгрд╛рд▓реАрдорд╛ рдкрд╣рд┐рд▓реЗ рдиреИ рдкреНрд░рдпреЛрдЧ рднрдЗрд╕рдХреЗрдХрд╛ рд╕рдВрдЦреНрдпрд╛рд╣рд░реВрд╕рдБрдЧ рднрд░реНрдЪреБрдЕрд▓ рд▓реЗрдирджреЗрди рд╣реБрди рд╕рдХреНрдЫ, рд░ рдпреЛ рд╕рд╛рдорд╛рдиреНрдп рд╣реЛред рддрд░ рдпрд╕реНрддреЛ рд╕рдВрдЦреНрдпрд╛ рдбрд╛рдЯрд╛ рдкреГрд╖реНрдард╣рд░реВрдорд╛ рд▓реЗрдЦреНрди рд╕рдХрд┐рдБрджреИрди, рдХрд┐рдирднрдиреЗ рдЕрд░реНрдХреЛ рдкрдЯрдХ рдкреГрд╖реНрда рдкрд╣реБрдБрдЪ рдЧрд░реНрджрд╛ рдпрд╕рд▓реЗ рд╕рдмреИ рдЕрд░реНрде рдЧреБрдорд╛рдЙрди рд╕рдХреНрдЫред

=> 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;

рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрди

рдЕрдВрдХрд╣рд░реВ рдмрдЪрдд рдЧрд░реНрдиреБрд╣реЛрд╕реН

SQL рдорд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЕрдВрдХ рдмрдЪрдд рдЧрд░реНрдиреБрд╣реЛрд╕реН (savepoint), рдЬрд╕рд▓реЗ рддрдкрд╛рдИрдВрд▓рд╛рдИ рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдЕрд╡рд░реЛрдз рдирдЧрд░реА рд▓реЗрдирджреЗрдирдХреЛ рдЕрдВрд╢ рд░рджреНрдж рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫред рддрд░ рдпреЛ рдорд╛рдерд┐рдХреЛ рд░реЗрдЦрд╛рдЪрд┐рддреНрд░рдорд╛ рдлрд┐рдЯ рд╣реБрдБрджреИрди, рдХрд┐рдирдХрд┐ рд▓реЗрдирджреЗрдирдорд╛ рд╕рдмреИ рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рд╕рдорд╛рди рд╕реНрдерд┐рддрд┐ рдЫ, рд░ рднреМрддрд┐рдХ рд░реВрдкрдорд╛ рдХреБрдиреИ рдбреЗрдЯрд╛ рдлрд┐рд░реНрддрд╛ рд╣реБрдБрджреИрдиред

рдпреЛ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд▓рд╛рдЧреВ рдЧрд░реНрди, рдмрдЪрдд рдкреЛрдЗрдиреНрдЯрдХреЛ рд╕рд╛рде рдПрдХ рд▓реЗрдирджреЗрди рдзреЗрд░реИ рдЕрд▓рдЧ рдорд╛ рд╡рд┐рднрд╛рдЬрд┐рдд рдЫ рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрди (рдЙрдкрд▓реЗрдирджреЗрди), рдЬрд╕рдХреЛ рд╕реНрдерд┐рддрд┐ рдЫреБрдЯреНрдЯреИ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрди рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫред

рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрдирдХреЛ рдЖрдлреНрдиреИ рдирдореНрдмрд░ рд╣реБрдиреНрдЫ (рдореБрдЦреНрдп рд▓реЗрдирджреЗрдирдХреЛ рд╕рдВрдЦреНрдпрд╛ рднрдиреНрджрд╛ рдмрдвреА)ред рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрдирдХреЛ рд╕реНрдерд┐рддрд┐ XACT рдорд╛ рд╕рд╛рдорд╛рдиреНрдп рддрд░рд┐рдХрд╛рдорд╛ рд░реЗрдХрд░реНрдб рдЧрд░рд┐рдПрдХреЛ рдЫ, рддрд░ рдЕрдиреНрддрд┐рдо рд╕реНрдерд┐рддрд┐ рдореБрдЦреНрдп рд▓реЗрдирджреЗрдирдХреЛ рд╕реНрдерд┐рддрд┐рдорд╛ рдирд┐рд░реНрднрд░ рдЧрд░реНрджрдЫ: рдпрджрд┐ рдпреЛ рд░рджреНрдж рдЧрд░рд┐рдпреЛ рднрдиреЗ, рд╕рдмреИ рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрдирд╣рд░реВ рдкрдирд┐ рд░рджреНрдж рд╣реБрдиреНрдЫрдиреНред

рд▓реЗрдирджреЗрди рдиреЗрд╕реНрдЯрд┐рдЩрдХреЛ рдмрд╛рд░реЗрдорд╛ рдЬрд╛рдирдХрд╛рд░реА PGDATA/pg_subtrans рдбрд╛рдЗрд░реЗрдХреНрдЯрд░реАрдорд╛ рдлрд╛рдЗрд▓рд╣рд░реВрдорд╛ рднрдгреНрдбрд╛рд░рдг рдЧрд░рд┐рдиреНрдЫред рдлрд╛рдЗрд▓рд╣рд░реВ рдЙрджрд╛рд╣рд░рдгрдХреЛ рд╕рд╛рдЭрд╛ рдореЗрдореЛрд░реАрдорд╛ рдмрдлрд░рд╣рд░реВ рдорд╛рд░реНрдлрдд рдкрд╣реБрдБрдЪ рдЧрд░рд┐рдиреНрдЫ, XACT рдмрдлрд░рд╣рд░реВ рдЬрд╕реНрддреИ рд╕рдВрдЧрдард┐рддред

рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрдирд╣рд░реВрд▓рд╛рдИ рд╕реНрд╡рд╛рдпрддреНрдд рд▓реЗрдирджреЗрдирд╣рд░реВрд╕рдБрдЧ рднреНрд░рдорд┐рдд рдирдЧрд░реНрдиреБрд╣реЛрд╕реНред рд╕реНрд╡рд╛рдпрддреНрдд рд▓реЗрдирджреЗрдирд╣рд░реВ рдХреБрдиреИ рдкрдирд┐ рд╣рд┐рд╕рд╛рдмрд▓реЗ рдПрдХрдЕрд░реНрдХрд╛рдорд╛ рдирд┐рд░реНрднрд░ рд╣реБрдБрджреИрди, рддрд░ рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрдирд╣рд░реВ рдЧрд░реНрдЫрдиреНред рддреНрдпрд╣рд╛рдБ рдирд┐рдпрдорд┐рдд 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)

рдЕрдм рдПрдЙрдЯрд╛ рдмрдЪрдд рдмрд┐рдиреНрджреБ рд░рд╛рдЦреМрдВ рд░ рдЕрд░реНрдХреЛ рд░реЗрдЦрд╛ рд╕рдореНрдорд┐рд▓рд┐рдд рдЧрд░реМрдВред

=> SAVEPOINT sp;
=> INSERT INTO t(s) VALUES ('XYZ');
=> SELECT txid_current();
 txid_current 
--------------
         3669
(1 row)

рдиреЛрдЯ рдЧрд░реНрдиреБрд╣реЛрд╕реН рдХрд┐ txid_current() рдкреНрд░рдХрд╛рд░реНрдпрд▓реЗ рдореБрдЦреНрдп рд▓реЗрдирджреЗрди рдирдореНрдмрд░ рдлрд░реНрдХрд╛рдЙрдБрдЫ, рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрди рдирдореНрдмрд░ рд╣реЛрдЗрдиред

=> 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)

рдмрдЪрдд рдмрд┐рдиреНрджреБрдорд╛ рдлрд┐рд░реНрддрд╛ рд░реЛрд▓ рдЧрд░реМрдВ рд░ рддреЗрд╕реНрд░реЛ рд░реЗрдЦрд╛ рд╕рдореНрдорд┐рд▓рд┐рдд рдЧрд░реМрдВред

=> 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)

рдкреГрд╖реНрдардорд╛ рд╣рд╛рдореА рд░рджреНрдж рдЧрд░рд┐рдПрдХреЛ рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрди рджреНрд╡рд╛рд░рд╛ рдердкрд┐рдПрдХреЛ рдкрдЩреНрдХреНрддрд┐ рджреЗрдЦреНрди рдЬрд╛рд░реА рд░рд╛рдЦреНрдЫреМрдВред

рд╣рд╛рдореА рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВ рдареАрдХ рдЧрд░реНрдЫреМрдВред

=> 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)

рдЕрдм рддрдкрд╛рдИрдВрд▓реЗ рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛ рджреЗрдЦреНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрдирдХреЛ рдЖрдлреНрдиреИ рд╕реНрдерд┐рддрд┐ рдЫред

рдиреЛрдЯ рдЧрд░реНрдиреБрд╣реЛрд╕реН рдХрд┐ рдиреЗрд╕реНрдЯреЗрдб рд▓реЗрдирджреЗрдирд╣рд░реВ SQL рдорд╛ рд╕реНрдкрд╖реНрдЯ рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХрд┐рдБрджреИрди, рдЕрд░реНрдерд╛рддреН, рддрдкрд╛рдИрдВрд▓реЗ рд╣рд╛рд▓рдХреЛ рдПрдХ рдкреВрд░рд╛ рдирдЧрд░реА рдирдпрд╛рдБ рдХрд╛рд░реЛрдмрд╛рд░ рд╕реБрд░реБ рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдиред рдмрдЪрдд рдкреЛрдЗрдиреНрдЯрд╣рд░реВ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрджрд╛, рд╕рд╛рдереИ 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 рд▓реЗ рд╡рд╛рд╕реНрддрд╡рдорд╛ рдкреНрд░рддреНрдпреЗрдХ рдХрдорд╛рдгреНрдб рдЕрдШрд┐ рдПрдХ рдирд┐рд╣рд┐рдд рдмрдЪрдд рдмрд┐рдиреНрджреБ рд░рд╛рдЦреНрдЫ, рд░ рдЕрд╕рдлрд▓рддрд╛рдХреЛ рдЕрд╡рд╕реНрдерд╛рдорд╛ рдпрд╕рд▓рд╛рдИ рд░реЛрд▓рдмреНрдпрд╛рдХ рд╕реБрд░реБ рдЧрд░реНрджрдЫред рдпреЛ рдореЛрдб рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдБрджреИрди, рдХрд┐рдирдХрд┐ рд╕реЗрдн рдкреЛрдЗрдиреНрдЯрд╣рд░реВ рд╕реЗрдЯ рдЧрд░реНрди (рддрд┐рдиреАрд╣рд░реВрдорд╛ рдлрд┐рд░реНрддрд╛ рдирд▓рд┐рдИ рдкрдирд┐) рдорд╣рддреНрддреНрд╡рдкреВрд░реНрдг рдУрднрд░рд╣реЗрдб рд╕рдорд╛рд╡реЗрд╢ рдЧрд░реНрджрдЫред

рдирд┐рд░рдиреНрддрд░рддрд╛ред

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди