MVCC-3. рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЖрд╡реГрддреНрддреНрдпрд╛

рдореНрд╣рдгреВрди, рдЖрдореНрд╣реА рд╕рдВрдмрдВрдзрд┐рдд рд╕рдорд╕реНрдпрд╛рдВрдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХреЗрд▓рд╛ рдЖрд╣реЗ рдЗрдиреНрд╕реБрд▓реЗрд╢рди, рдЖрдгрд┐ рдмрджреНрджрд▓ рдорд╛рдШрд╛рд░ рдШреЗрддрд▓реА рдирд┐рдореНрди рд╕реНрддрд░рд╛рд╡рд░ рдбреЗрдЯрд╛ рдЖрдпреЛрдЬрд┐рдд рдХрд░рдгреЗ. рдЖрдгрд┐ рд╢реЗрд╡рдЯреА рдЖрдореНрд╣реА рд╕рд░реНрд╡рд╛рдд рдордиреЛрд░рдВрдЬрдХ рднрд╛рдЧрд╛рд╡рд░ рдкреЛрд╣реЛрдЪрд▓реЛ - рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЖрд╡реГрддреНрддреНрдпрд╛.

рд╢реАрд░реНрд╖рд▓реЗрдЦ

рдЖрдореНрд╣реА рдЖрдзреАрдЪ рдореНрд╣рдЯрд▓реНрдпрд╛рдкреНрд░рдорд╛рдгреЗ, рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддреА рдбреЗрдЯрд╛рдмреЗрд╕рдордзреАрд▓ рдЕрдиреЗрдХ рдЖрд╡реГрддреНрддреНрдпрд╛рдВрдордзреНрдпреЗ рдПрдХрд╛рдЪ рд╡реЗрд│реА рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдЕрд╕реВ рд╢рдХрддреЗ. рдПрдХ рдЖрд╡реГрддреНрддреА рджреБрд╕рд░реНтАНрдпрд╛рдкреЗрдХреНрд╖рд╛ рдХрд╢реА рддрд░реА рд╡реЗрдЧрд│реА рдЕрд╕рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдпрд╛ рдЙрджреНрджреЗрд╢рд╛рд╕рд╛рдареА, рдкреНрд░рддреНрдпреЗрдХ рдЖрд╡реГрддреНрддреАрдЪреЗ рджреЛрди рдЧреБрдг рдЖрд╣реЗрдд рдЬреЗ рдпрд╛ рдЖрд╡реГрддреНрддреАрдЪреНрдпрд╛ рдХреНрд░рд┐рдпреЗрдЪреА "рд╡реЗрд│" рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛рдд (xmin рдЖрдгрд┐ xmax). рдЕрд╡рддрд░рдгрд╛рдВрдордзреНрдпреЗ - рдХрд╛рд░рдг рддреА рд╡реЗрд│ рдирд╛рд╣реА рдЬреА рд╡рд╛рдкрд░рд▓реА рдЬрд╛рддреЗ, рдкрд░рдВрддреБ рд╡рд┐рд╢реЗрд╖ рд╡рд╛рдврдгрд╛рд░реА рдХрд╛рдЙрдВрдЯрд░. рдЖрдгрд┐ рд╣рд╛ рдХрд╛рдЙрдВрдЯрд░ рдореНрд╣рдгрдЬреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреНрд░рдорд╛рдВрдХ.

(рдиреЗрд╣рдореАрдкреНрд░рдорд╛рдгреЗ, рд╡рд╛рд╕реНрддрд╡рд┐рдХрддрд╛ рдЕрдзрд┐рдХ рдХреНрд▓рд┐рд╖реНрдЯ рдЖрд╣реЗ: рдХрд╛рдЙрдВрдЯрд░рдЪреНрдпрд╛ рдорд░реНрдпрд╛рджрд┐рдд рдмрд┐рдЯ рдХреНрд╖рдорддреЗрдореБрд│реЗ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдЪреА рд╕рдВрдЦреНрдпрд╛ рдиреЗрд╣рдореАрдЪ рд╡рд╛рдвреВ рд╢рдХрдд рдирд╛рд╣реА. рдкрд░рдВрддреБ рдЬреЗрд╡реНрд╣рд╛ рдЖрдкрдг рдЧреЛрдард╡реВ рддреЗрд╡реНрд╣рд╛ рдЖрдореНрд╣реА рд╣реЗ рддрдкрд╢реАрд▓ рддрдкрд╢реАрд▓рд╡рд╛рд░ рдкрд╛рд╣реВ.)

рдПрдХ рдкрдВрдХреНрддреА рддрдпрд╛рд░ рдХреЗрд▓реНрдпрд╛рд╡рд░, INSERT рдЖрджреЗрд╢ рдЬрд╛рд░реА рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреНрд░рдорд╛рдВрдХрд╛рд╡рд░ xmin рд╕реЗрдЯ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ рдЖрдгрд┐ xmax рд░рд┐рдХреНрдд рдареЗрд╡рд▓рд╛ рдЬрд╛рддреЛ.

рдЬреЗрд╡реНрд╣рд╛ рдПрдЦрд╛рджреА рдкрдВрдХреНрддреА рд╣рдЯрд╡рд┐рд▓реА рдЬрд╛рддреЗ, рддреЗрд╡реНрд╣рд╛ рд╡рд░реНрддрдорд╛рди рдЖрд╡реГрддреНрддреАрдЪреЗ xmax рдореВрд▓реНрдп DELETE рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдЪреНрдпрд╛ рд╕рдВрдЦреНрдпреЗрд╕рд╣ рдЪрд┐рдиреНрд╣рд╛рдВрдХрд┐рдд рдХреЗрд▓реЗ рдЬрд╛рддреЗ.

рдЕрджреНрдпрдпрд╛рд╡рдд рдХрдорд╛рдВрдбрджреНрд╡рд╛рд░реЗ рдкрдВрдХреНрддреА рд╕реБрдзрд╛рд░рд▓реА рдЬрд╛рддреЗ рддреЗрд╡реНрд╣рд╛, рджреЛрди рдСрдкрд░реЗрд╢рдиреНрд╕ рдкреНрд░рддреНрдпрдХреНрд╖рд╛рдд рдХреЗрд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд: рд╣рдЯрд╡рд╛ рдЖрдгрд┐ рдШрд╛рд▓рд╛. рдкрдВрдХреНрддреАрдЪреА рд╡рд░реНрддрдорд╛рди рдЖрд╡реГрддреНрддреА рдЕрдкрдбреЗрдЯ рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдЪреНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдЗрддрдХреА xmax рд╕реЗрдЯ рдХрд░рддреЗ. рдирдВрддрд░ рддреНрдпрд╛рдЪ рд╕реНрдЯреНрд░рд┐рдВрдЧрдЪреА рдирд╡реАрди рдЖрд╡реГрддреНрддреА рддрдпрд╛рд░ рдХреЗрд▓реА рдЬрд╛рддреЗ; рддреНрдпрд╛рдЪреЗ xmin рдореВрд▓реНрдп рдорд╛рдЧреАрд▓ рдЖрд╡реГрддреНрддреАрдЪреНрдпрд╛ xmax рдореВрд▓реНрдпрд╛рд╢реА рдЬреБрд│рддреЗ.

xmin рдЖрдгрд┐ xmax рдлреАрд▓реНрдб рдкрдВрдХреНрддреА рдЖрд╡реГрддреНрддреА рд╢реАрд░реНрд╖рд▓реЗрдЦ рдордзреНрдпреЗ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдЖрд╣реЗрдд. рдпрд╛ рдлреАрд▓реНрдб рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рд╢реАрд░реНрд╖рд▓реЗрдЦрд╛рдд рдЗрддрд░ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдЖрд╣реЗрдд, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде:

  • рдЗрдиреНрдлреЛрдорд╛рд╕реНрдХ рд╣реА рдмрд┐рдЯреНрд╕рдЪреА рдорд╛рд▓рд┐рдХрд╛ рдЖрд╣реЗ рдЬреА рдпрд╛ рдЖрд╡реГрддреНрддреАрдЪреЗ рдЧреБрдгрдзрд░реНрдо рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ. рддреНрдпрд╛рдкреИрдХреА рдмрд░реЗрдЪ рдЖрд╣реЗрдд; рдЖрдореНрд╣реА рд╣рд│реВрд╣рд│реВ рдореБрдЦреНрдп рдЧреЛрд╖реНрдЯреАрдВрдЪрд╛ рд╡рд┐рдЪрд╛рд░ рдХрд░реВ.
  • ctid рд╣реА рддреНрдпрд╛рдЪ рдУрд│реАрдЪреНрдпрд╛ рдкреБрдвреАрд▓, рдирд╡реАрди рдЖрд╡реГрддреНрддреАрдЪреА рд▓рд┐рдВрдХ рдЖрд╣реЗ. рд╕реНрдЯреНрд░рд┐рдВрдЧрдЪреНрдпрд╛ рдирд╡реАрдирддрдо, рд╕рд░реНрд╡рд╛рдд рд╡рд░реНрддрдорд╛рди рдЖрд╡реГрддреНрддреАрд╕рд╛рдареА, ctid рдпрд╛ рдЖрд╡реГрддреНрддреАрдЪрд╛рдЪ рд╕рдВрджрд░реНрдн рджреЗрддреЗ. рдирдВрдмрд░рдордзреНрдпреЗ рдлреЙрд░реНрдо (x,y) рдЖрд╣реЗ, рдЬреЗрдереЗ x рд╣рд╛ рдкреГрд╖реНрда рдХреНрд░рдорд╛рдВрдХ рдЖрд╣реЗ, y рд╣рд╛ рдЕреЕрд░реЗрдордзреАрд▓ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреНрд░рдорд╛рдВрдХ рдЖрд╣реЗ.
  • null bitmap - рджрд┐рд▓реЗрд▓реНрдпрд╛ рдЖрд╡реГрддреНрддреАрдЪреНрдпрд╛ рддреНрдпрд╛ рд╕реНрддрдВрднрд╛рдВрдирд╛ рдЪрд┐рдиреНрд╣рд╛рдВрдХрд┐рдд рдХрд░рддреЗ рдЬреНрдпрд╛рдд рд╢реВрдиреНрдп рдореВрд▓реНрдп (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)

рдЪрд▓рд╛ рдкреГрд╖реНрдард╛рд╡рд░реАрд▓ рд╕рд╛рдордЧреНрд░реА рдкрд╛рд╣реВ. рдкреЗрдЬрдЗрдиреНрд╕реНрдкреЗрдХреНрдЯ рдПрдХреНрд╕реНрдЯреЗрдВрд╢рдирдЪреЗ 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 рдордзреАрд▓ 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 рдкреЙрдЗрдВрдЯрд░рдЪреА рд╕реНрдерд┐рддреА рдЙрд▓рдЧрдбрд▓реА. рдпреЗрдереЗ рддреЗ "рд╕рд╛рдорд╛рдиреНрдп" рдЖрд╣реЗ - рдпрд╛рдЪрд╛ рдЕрд░реНрде рдЕрд╕рд╛ рдХреА рдкреЙрдЗрдВрдЯрд░ рдкреНрд░рддреНрдпрдХреНрд╖рд╛рдд рд╕реНрдЯреНрд░рд┐рдВрдЧрдЪреНрдпрд╛ рдЖрд╡реГрддреНрддреАрдЪрд╛ рд╕рдВрджрд░реНрдн рджреЗрддреЛ. рдЗрддрд░ рдЕрд░реНрде рдЖрдкрдг рдирдВрддрд░ рдкрд╛рд╣реВ.
  • рд╕рд░реНрд╡ рдорд╛рд╣рд┐рддреА рдмрд┐рдЯреНрд╕рдкреИрдХреА, рдЖрддрд╛рдкрд░реНрдпрдВрдд рдлрдХреНрдд рджреЛрди рдЬреЛрдбреНрдпрд╛ рдУрд│рдЦрд▓реНрдпрд╛ рдЧреЗрд▓реНрдпрд╛ рдЖрд╣реЗрдд. xmin_committed рдЖрдгрд┐ xmin_aborted рдмрд┐рдЯреНрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреНрд░рдорд╛рдВрдХ xmin рдХрдорд┐рдЯреЗрдб рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рд╣реЗ рд╕реВрдЪрд┐рдд рдХрд░рддрд╛рдд (рд░рджреНрдж рдХреЗрд▓реЗрд▓реЗ). рджреЛрди рд╕рдорд╛рди рдмрд┐рдЯ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреНрд░рдорд╛рдВрдХ xmax рдЪрд╛ рд╕рдВрджрд░реНрдн рджреЗрддрд╛рдд.

рдЖрдореНрд╣реА рдХрд╛рдп рдкрд╛рд╣рддреЛ? рдЬреЗрд╡реНрд╣рд╛ рддреБрдореНрд╣реА рдкрдВрдХреНрддреА рдШрд╛рд▓рд╛рд▓, рддреЗрд╡реНрд╣рд╛ рдкрдВрдХреНрддреАрдЪреНрдпрд╛ рдкрд╣рд┐рд▓реНрдпрд╛ рдЖрдгрд┐ рдПрдХрдореЗрд╡ рдЖрд╡реГрддреНрддреАрдХрдбреЗ рдирд┐рд░реНрджреЗрд╢ рдХрд░реВрди, рд╕рд╛рд░рдгреАрдЪреНрдпрд╛ рдкреГрд╖реНрдард╛рд╡рд░ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреНрд░рдорд╛рдВрдХ 1 рджрд┐рд╕реЗрд▓.

рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЖрд╡реГрддреНрддреАрдордзреНрдпреЗ, xmin рдлреАрд▓реНрдб рд╕рдзреНрдпрд╛рдЪреНрдпрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреНрд░рдорд╛рдВрдХрд╛рдиреЗ рднрд░рд▓реЗрд▓реЗ рдЖрд╣реЗ. рд╡реНрдпрд╡рд╣рд╛рд░ рдЕрджреНрдпрд╛рдк рд╕рдХреНрд░рд┐рдп рдЖрд╣реЗ, рддреНрдпрд╛рдореБрд│реЗ xmin_committed рдЖрдгрд┐ xmin_aborted рдмрд┐рдЯ рд╕реЗрдЯ рдХреЗрд▓реЗрд▓реЗ рдирд╛рд╣реАрдд.

рдкрдВрдХреНрддреА рдЖрд╡реГрддреНрддреА ctid рдлреАрд▓реНрдб рд╕рдорд╛рди рдкрдВрдХреНрддреАрдЪрд╛ рд╕рдВрджрд░реНрдн рджреЗрддреЗ. рдпрд╛рдЪрд╛ рдЕрд░реНрде рдирд╡реАрди рдЖрд╡реГрддреНрддреА рдЕрд╕реНрддрд┐рддреНрд╡рд╛рдд рдирд╛рд╣реА.

xmax рдлреАрд▓реНрдб рдбрдореА рдХреНрд░рдорд╛рдВрдХ 0 рдиреЗ рднрд░рд▓реЗ рдЖрд╣реЗ рдХрд╛рд░рдг рдкрдВрдХреНрддреАрдЪреА рд╣реА рдЖрд╡реГрддреНрддреА рд╣рдЯрд╡рд┐рд▓реА рдЧреЗрд▓реА рдирд╛рд╣реА рдЖрдгрд┐ рддреА рд╕рдзреНрдпрд╛рдЪреА рдЖрд╣реЗ. 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;

рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ

рдЖрддрд╛рдкрд░реНрдпрдВрдд рдЖрдкрдг рдлрдХреНрдд рдЯреЗрдмрд▓рдЪреНрдпрд╛ рдкрд╛рдирд╛рдВрдмрджреНрджрд▓ рдмреЛрд▓рд▓реЛ рдЖрд╣реЛрдд. рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХрд╛рдВрдордзреНрдпреЗ рдХрд╛рдп рд╣реЛрддреЗ?

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

рддрдерд╛рдкрд┐, рдкреГрд╖реНрдард╛рдордзреНрдпреЗ рд╕рд╛рдорд╛рдиреНрдпрддрдГ рдкрдВрдХреНрддреА рдЖрдгрд┐ рдкрдВрдХреНрддреАрдВрдХрдбреЗ рдкреЙрдЗрдВрдЯрд░рдЪреА рдЕтАНреЕрд░реЗ рдЕрд╕рддреЗ (рдлрдХреНрдд рд╕рд╛рд░рдгреА рдкреГрд╖реНрдард╛рдкреНрд░рдорд╛рдгреЗ). рдпрд╛рд╡реНрдпрддрд┐рд░рд┐рдХреНрдд, рдкреГрд╖реНрдард╛рдЪреНрдпрд╛ рд╢реЗрд╡рдЯреА рд╡рд┐рд╢реЗрд╖ рдбреЗрдЯрд╛рд╕рд╛рдареА рдЬрд╛рдЧрд╛ рдЖрд╣реЗ.

рдЕрдиреБрдХреНрд░рдордгрд┐рдХреЗрдЪреНрдпрд╛ рдкрдВрдХреНрддреАрдВрдордзреНрдпреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХрд╛рдЪреНрдпрд╛ рдкреНрд░рдХрд╛рд░рд╛рдиреБрд╕рд╛рд░ рдЦреВрдк рднрд┐рдиреНрди рд░рдЪрдирд╛ рджреЗрдЦреАрд▓ рдЕрд╕реВ рд╢рдХрддрд╛рдд. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдмреА-рдЯреНрд░реАрд╕рд╛рдареА, рдкрд╛рдирд╛рдВрдЪреНрдпрд╛ рдкрд╛рдирд╛рдВрд╢реА рд╕рдВрдмрдВрдзрд┐рдд рдкрдВрдХреНрддреАрдВрдордзреНрдпреЗ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдХреА рдореВрд▓реНрдп рдЖрдгрд┐ рд╕рдВрдмрдВрдзрд┐рдд рд╕рд╛рд░рдгреА рдкрдВрдХреНрддреАрдЪрд╛ рд╕рдВрджрд░реНрдн (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 рдордзреНрдпреЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЧреБрдг рдЬрддрди рдХрд░рд╛ (рд╕реЗрд╡реНрд╣рдкреЙрдЗрдВрдЯ), рдЬреЗ рддреБрдореНрд╣рд╛рд▓рд╛ рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдЪрд╛ рднрд╛рдЧ рдкреВрд░реНрдгрдкрдгреЗ рд╡реНрдпрддреНрдпрдп рди рдЖрдгрддрд╛ рд░рджреНрдж рдХрд░рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрддреЗ. рдкрд░рдВрддреБ рд╣реЗ рд╡рд░реАрд▓ рдЖрдХреГрддреАрдордзреНрдпреЗ рдмрд╕рдд рдирд╛рд╣реА, рдХрд╛рд░рдг рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдд рд╕рд░реНрд╡ рдмрджрд▓рд╛рдВрд╕рд╛рдареА рд╕рдорд╛рди рд╕реНрдерд┐рддреА рдЖрд╣реЗ рдЖрдгрд┐ рднреМрддрд┐рдХрджреГрд╖реНрдЯреНрдпрд╛ рдХреЛрдгрддрд╛рд╣реА рдбреЗрдЯрд╛ рдкрд░рдд рдХреЗрд▓рд╛ рдЬрд╛рдд рдирд╛рд╣реА.

рд╣реА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдЕрдВрдорд▓рд╛рдд рдЖрдгрдгреНрдпрд╛рд╕рд╛рдареА, рд╕реЗрд╡реНрд╣рдкреЙрдИрдВрдЯрд╕рд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдЕрдиреЗрдХ рд╡рд┐рднрдХреНрддрд╛рдВрдордзреНрдпреЗ рд╡рд┐рднрд╛рдЧрд▓рд╛ рдЬрд╛рддреЛ рдиреЗрд╕реНрдЯреЗрдб рд╡реНрдпрд╡рд╣рд╛рд░ (рдЙрдкрд╡реНрдпрд╡рд╣рд╛рд░), рдЬреНрдпрд╛рдЪреА рд╕реНрдерд┐рддреА рд╕реНрд╡рддрдВрддреНрд░рдкрдгреЗ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрд┐рдд рдХреЗрд▓реА рдЬрд╛рдК рд╢рдХрддреЗ.

рдиреЗрд╕реНрдЯреЗрдб рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдВрдЪреА рд╕реНрд╡рддрдГрдЪреА рд╕рдВрдЦреНрдпрд╛ рдЕрд╕рддреЗ (рдореБрдЦреНрдп рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдЪреНрдпрд╛ рд╕рдВрдЦреНрдпреЗрдкреЗрдХреНрд╖рд╛ рдЬрд╛рд╕реНрдд). рдиреЗрд╕реНрдЯреЗрдб рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдВрдЪреА рд╕реНрдерд┐рддреА 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

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛