ΠΡΠ°ΠΊ, ΠΌΡ ΡΠ°ΡΡΠΌΠΎΡΡΠ΅Π»ΠΈ Π²ΠΎΠΏΡΠΎΡΡ, ΡΠ²ΡΠ·Π°Π½Π½ΡΠ΅ Ρ
ΠΠ°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ
ΠΠ°ΠΊ ΠΌΡ ΡΠΆΠ΅ Π³ΠΎΠ²ΠΎΡΠΈΠ»ΠΈ, ΠΊΠ°ΠΆΠ΄Π°Ρ ΡΡΡΠΎΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ ΠΎΠ΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ ΠΏΡΠΈΡΡΡΡΡΠ²ΠΎΠ²Π°ΡΡ Π² Π±Π°Π·Π΅ Π΄Π°Π½Π½ΡΡ Π² Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ Π²Π΅ΡΡΠΈΡΡ . ΠΠ΄Π½Ρ Π²Π΅ΡΡΠΈΡ ΠΎΡ Π΄ΡΡΠ³ΠΎΠΉ Π½Π°Π΄ΠΎ ΠΊΠ°ΠΊ-ΡΠΎ ΠΎΡΠ»ΠΈΡΠ°ΡΡ Π‘ ΡΡΠΎΠΉ ΡΠ΅Π»ΡΡ ΠΊΠ°ΠΆΠ΄Π°Ρ Π²Π΅ΡΡΠΈΡ ΠΈΠΌΠ΅Π΅Ρ Π΄Π²Π΅ ΠΎΡΠΌΠ΅ΡΠΊΠΈ, ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡΠΈΠ΅ Β«Π²ΡΠ΅ΠΌΡΒ» Π΄Π΅ΠΉΡΡΠ²ΠΈΡ Π΄Π°Π½Π½ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ (xmin ΠΈ xmax). Π ΠΊΠ°Π²ΡΡΠΊΠ°Ρ β ΠΏΠΎΡΠΎΠΌΡ, ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π½Π΅ Π²ΡΠ΅ΠΌΡ ΠΊΠ°ΠΊ ΡΠ°ΠΊΠΎΠ²ΠΎΠ΅, Π° ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠΉ ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°ΡΡΠΈΠΉΡΡ ΡΡΠ΅ΡΡΠΈΠΊ. Π ΡΡΠΎΡ ΡΡΠ΅ΡΡΠΈΠΊ β Π½ΠΎΠΌΠ΅Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ.
(ΠΠ°ΠΊ ΠΎΠ±ΡΡΠ½ΠΎ, Π½Π° ΡΠ°ΠΌΠΎΠΌ Π΄Π΅Π»Π΅ Π²ΡΠ΅ ΡΠ»ΠΎΠΆΠ½Π΅Π΅: Π½ΠΎΠΌΠ΅Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΉ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠ΅ Π²ΡΠ΅ΠΌΡ ΡΠ²Π΅Π»ΠΈΡΠΈΠ²Π°ΡΡΡΡ ΠΈΠ·-Π·Π° ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½Π½ΠΎΠΉ ΡΠ°Π·ΡΡΠ΄Π½ΠΎΡΡΠΈ ΡΡΠ΅ΡΡΠΈΠΊΠ°. ΠΠΎ ΡΡΠΈ Π΄Π΅ΡΠ°Π»ΠΈ ΠΌΡ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ, ΠΊΠΎΠ³Π΄Π° Π΄ΠΎΠΉΠ΄Π΅ΠΌ Π΄ΠΎ Π·Π°ΠΌΠΎΡΠΎΠ·ΠΊΠΈ.)
ΠΠΎΠ³Π΄Π° ΡΡΡΠΎΠΊΠ° ΡΠΎΠ·Π΄Π°Π΅ΡΡΡ, Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ xmin ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΡΡΡ Π² Π½ΠΎΠΌΠ΅Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ, Π²ΡΠΏΠΎΠ»Π½ΠΈΠ²ΡΠ΅ΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ INSERT, Π° xmax Π½Π΅ Π·Π°ΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ.
ΠΠΎΠ³Π΄Π° ΡΡΡΠΎΠΊΠ° ΡΠ΄Π°Π»ΡΠ΅ΡΡΡ, Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ xmax ΡΠ΅ΠΊΡΡΠ΅ΠΉ Π²Π΅ΡΡΠΈΠΈ ΠΏΠΎΠΌΠ΅ΡΠ°Π΅ΡΡΡ Π½ΠΎΠΌΠ΅ΡΠΎΠΌ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ, Π²ΡΠΏΠΎΠ»Π½ΠΈΠ²ΡΠ΅ΠΉ DELETE.
ΠΠΎΠ³Π΄Π° ΡΡΡΠΎΠΊΠ° ΠΈΠ·ΠΌΠ΅Π½ΡΠ΅ΡΡΡ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ UPDATE, ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π΄Π²Π΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ: DELETE ΠΈ INSERT. Π ΡΠ΅ΠΊΡΡΠ΅ΠΉ Π²Π΅ΡΡΠΈΠΈ ΡΡΡΠΎΠΊΠΈ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΡΡΡ xmax, ΡΠ°Π²Π½ΡΠΉ Π½ΠΎΠΌΠ΅ΡΡ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ, Π²ΡΠΏΠΎΠ»Π½ΠΈΠ²ΡΠ΅ΠΉ UPDATE. ΠΠ°ΡΠ΅ΠΌ ΡΠΎΠ·Π΄Π°Π΅ΡΡΡ Π½ΠΎΠ²Π°Ρ Π²Π΅ΡΡΠΈΡ ΡΠΎΠΉ ΠΆΠ΅ ΡΡΡΠΎΠΊΠΈ; Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ xmin Ρ Π½Π΅Π΅ ΡΠΎΠ²ΠΏΠ°Π΄Π°Π΅Ρ Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ xmax ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅ΠΉ Π²Π΅ΡΡΠΈΠΈ.
ΠΠΎΠ»Ρ xmin ΠΈ xmax Π²Ρ ΠΎΠ΄ΡΡ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Π²Π΅ΡΡΠΈΠΈ ΡΡΡΠΎΠΊΠΈ. ΠΡΠΎΠΌΠ΅ ΡΡΠΈΡ ΠΏΠΎΠ»Π΅ΠΉ, Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ:
- infomask β ΡΡΠ΄ Π±ΠΈΡΠΎΠ², ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΡΡΠΈΡ ΡΠ²ΠΎΠΉΡΡΠ²Π° Π΄Π°Π½Π½ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ. ΠΡ Π΄ΠΎΠ²ΠΎΠ»ΡΠ½ΠΎ ΠΌΠ½ΠΎΠ³ΠΎ; ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΈΠ· Π½ΠΈΡ ΠΌΡ ΠΏΠΎΡΡΠ΅ΠΏΠ΅Π½Π½ΠΎ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ.
- ctid β ΡΡΡΠ»ΠΊΠ° Π½Π° ΡΠ»Π΅Π΄ΡΡΡΡΡ, Π±ΠΎΠ»Π΅Π΅ Π½ΠΎΠ²ΡΡ, Π²Π΅ΡΡΠΈΡ ΡΠΎΠΉ ΠΆΠ΅ ΡΡΡΠΎΠΊΠΈ. Π£ ΡΠ°ΠΌΠΎΠΉ Π½ΠΎΠ²ΠΎΠΉ, Π°ΠΊΡΡΠ°Π»ΡΠ½ΠΎΠΉ, Π²Π΅ΡΡΠΈΠΈ ΡΡΡΠΎΠΊΠΈ ctid ΡΡΡΠ»Π°Π΅ΡΡΡ Π½Π° ΡΠ°ΠΌΡ ΡΡΡ Π²Π΅ΡΡΠΈΡ. ΠΠΎΠΌΠ΅Ρ ΠΈΠΌΠ΅Π΅Ρ Π²ΠΈΠ΄ (x,y), Π³Π΄Π΅ x β Π½ΠΎΠΌΠ΅Ρ ΡΡΡΠ°Π½ΠΈΡΡ, y β ΠΏΠΎΡΡΠ΄ΠΊΠΎΠ²ΡΠΉ Π½ΠΎΠΌΠ΅Ρ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π² ΠΌΠ°ΡΡΠΈΠ²Π΅.
- Π±ΠΈΡΠΎΠ²Π°Ρ ΠΊΠ°ΡΡΠ° Π½Π΅ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ β ΠΎΡΠΌΠ΅ΡΠ°Π΅Ρ ΡΠ΅ ΡΡΠΎΠ»Π±ΡΡ Π΄Π°Π½Π½ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠ°Ρ Π½Π΅ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ (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 ΡΠ°ΡΡΠΈΡΠ΅Π½ΠΈΡ pageinspect ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎΠ± ΡΠΊΠ°Π·Π°ΡΠ΅Π»ΡΡ ΠΈ Π²Π΅ΡΡΠΈΡΡ ΡΡΡΠΎΠΊ:
=> 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
ΠΠ°ΠΌΠ΅ΡΠΈΠΌ, ΡΡΠΎ ΡΠ»ΠΎΠ²ΠΎΠΌ heap (ΠΊΡΡΠ°) Π² 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. ΠΠ΄Π΅ΡΡ ΠΎΠ½ Β«normalΒ» β ΡΡΠΎ Π·Π½Π°ΡΠΈΡ, ΡΡΠΎ ΡΠΊΠ°Π·Π°ΡΠ΅Π»Ρ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ ΡΡΡΠ»Π°Π΅ΡΡΡ Π½Π° Π²Π΅ΡΡΠΈΡ ΡΡΡΠΎΠΊΠΈ. ΠΡΡΠ³ΠΈΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΏΠΎΠ·ΠΆΠ΅.
- ΠΠ· Π²ΡΠ΅Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΠΎΠ½Π½ΡΡ Π±ΠΈΡΠΎΠ² Π²ΡΠ΄Π΅Π»ΠΈΠ»ΠΈ ΠΏΠΎΠΊΠ° ΡΠΎΠ»ΡΠΊΠΎ Π΄Π²Π΅ ΠΏΠ°ΡΡ. ΠΠΈΡΡ 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 (commit log) ΠΈ ΡΡΠΎ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ Π΅ΡΠ΅ ΠΌΠΎΠΆΠ΅Ρ Π²ΡΡΡΠ΅ΡΠ°ΡΡΡΡ Π² ΡΠ°Π·Π½ΡΡ ΠΌΠ΅ΡΡΠ°Ρ ).
XACT β Π½Π΅ ΡΠ°Π±Π»ΠΈΡΠ° ΡΠΈΡΡΠ΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π°; ΡΡΠΎ ΡΠ°ΠΉΠ»Ρ Π² ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π΅ PGDATA/pg_xact. Π Π½ΠΈΡ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ ΠΎΡΠ²Π΅Π΄Π΅Π½ΠΎ Π΄Π²Π° Π±ΠΈΡΠ°: committed ΠΈ aborted β ΡΠΎΡΠ½ΠΎ ΡΠ°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅ Π²Π΅ΡΡΠΈΠΈ ΡΡΡΠΎΠΊΠΈ. ΠΠ° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ°ΠΉΠ»ΠΎΠ² ΡΡΠ° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΡΠ°Π·Π±ΠΈΡΠ° ΠΈΡΠΊΠ»ΡΡΠΈΡΠ΅Π»ΡΠ½ΠΎ Π΄Π»Ρ ΡΠ΄ΠΎΠ±ΡΡΠ²Π°, ΠΌΡ Π΅ΡΠ΅ Π²Π΅ΡΠ½Π΅ΠΌΡΡ ΠΊ ΡΡΠΎΠΌΡ Π²ΠΎΠΏΡΠΎΡΡ, ΠΊΠΎΠ³Π΄Π° Π±ΡΠ΄Π΅ΠΌ ΡΠ°ΡΡΠΌΠ°ΡΡΠΈΠ²Π°ΡΡ Π·Π°ΠΌΠΎΡΠΎΠ·ΠΊΡ. Π ΡΠ°Π±ΠΎΡΠ° Ρ ΡΡΠΈΠΌΠΈ ΡΠ°ΠΉΠ»Π°ΠΌΠΈ Π²Π΅Π΄Π΅ΡΡΡ ΠΏΠΎΡΡΡΠ°Π½ΠΈΡΠ½ΠΎ, ΠΊΠ°ΠΊ ΠΈ ΡΠΎ Π²ΡΠ΅ΠΌΠΈ Π΄ΡΡΠ³ΠΈΠΌΠΈ.
ΠΡΠ°ΠΊ, ΠΏΡΠΈ ΡΠΈΠΊΡΠ°ΡΠΈΠΈ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ Π² XACT Π²ΡΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π±ΠΈΡ committed Π΄Π»Ρ Π΄Π°Π½Π½ΠΎΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ. Π ΡΡΠΎ Π²ΡΠ΅, ΡΡΠΎ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΠΏΡΠΈ ΡΠΈΠΊΡΠ°ΡΠΈΠΈ (ΠΏΡΠ°Π²Π΄Π°, ΠΌΡ ΠΏΠΎΠΊΠ° Π½Π΅ Π³ΠΎΠ²ΠΎΡΠΈΠΌ ΠΏΡΠΎ ΠΆΡΡΠ½Π°Π» ΠΏΡΠ΅Π΄Π·Π°ΠΏΠΈΡΠΈ).
ΠΠΎΠ³Π΄Π° ΠΊΠ°ΠΊΠ°Ρ-Π»ΠΈΠ±ΠΎ Π΄ΡΡΠ³Π°Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡ ΠΎΠ±ΡΠ°ΡΠΈΡΡΡ ΠΊ ΡΠ°Π±Π»ΠΈΡΠ½ΠΎΠΉ ΡΡΡΠ°Π½ΠΈΡΠ΅, Π½Π° ΠΊΠΎΡΠΎΡΡΡ ΠΌΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠΎ ΡΠΌΠΎΡΡΠ΅Π»ΠΈ, Π΅ΠΉ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΠΎΡΠ²Π΅ΡΠΈΡΡ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ Π²ΠΎΠΏΡΠΎΡΠΎΠ².
- ΠΠ°Π²Π΅ΡΡΠΈΠ»Π°ΡΡ Π»ΠΈ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡ xmin? ΠΡΠ»ΠΈ Π½Π΅Ρ, ΡΠΎ ΡΠΎΠ·Π΄Π°Π½Π½Π°Ρ Π²Π΅ΡΡΠΈΡ ΡΡΡΠΎΠΊΠΈ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Π° Π±ΡΡΡ Π²ΠΈΠ΄Π½Π°.
Π’Π°ΠΊΠ°Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΠΏΡΠΎΡΠΌΠΎΡΡΠΎΠΌ Π΅ΡΠ΅ ΠΎΠ΄Π½ΠΎΠΉ ΡΡΡΡΠΊΡΡΡΡ, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠ°ΡΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ Π² ΠΎΠ±ΡΠ΅ΠΉ ΠΏΠ°ΠΌΡΡΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° ΠΈ Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ ProcArray. Π Π½Π΅ΠΉ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ ΡΠΏΠΈΡΠΎΠΊ Π²ΡΠ΅Ρ Π°ΠΊΡΠΈΠ²Π½ΡΡ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ², ΠΈ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡΠΊΠ°Π·Π°Π½ Π½ΠΎΠΌΠ΅Ρ Π΅Π³ΠΎ ΡΠ΅ΠΊΡΡΠ΅ΠΉ (Π°ΠΊΡΠΈΠ²Π½ΠΎΠΉ) ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ. - ΠΡΠ»ΠΈ Π·Π°Π²Π΅ΡΡΠΈΠ»Π°ΡΡ, ΡΠΎ ΠΊΠ°ΠΊ β ΡΠΈΠΊΡΠ°ΡΠΈΠ΅ΠΉ ΠΈΠ»ΠΈ ΠΎΡΠΌΠ΅Π½ΠΎΠΉ? ΠΡΠ»ΠΈ ΠΎΡΠΌΠ΅Π½ΠΎΠΉ, ΡΠΎ Π²Π΅ΡΡΠΈΡ ΡΡΡΠΎΠΊΠΈ ΡΠΎΠΆΠ΅ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ Π±ΡΡΡ Π²ΠΈΠ΄Π½Π°.
ΠΠΎΡ Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ ΠΊΠ°ΠΊ ΡΠ°Π· ΠΈ Π½ΡΠΆΠ΅Π½ XACT. ΠΠΎ, Ρ ΠΎΡΡ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ ΡΡΡΠ°Π½ΠΈΡΡ XACT ΡΠΎΡ ΡΠ°Π½ΡΡΡΡΡ Π² Π±ΡΡΠ΅ΡΠ°Ρ Π² ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΎΠΉ ΠΏΠ°ΠΌΡΡΠΈ, Π²ΡΠ΅ ΠΆΠ΅ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΠ°Π· ΠΏΡΠΎΠ²Π΅ΡΡΡΡ 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. ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ ΠΏΡΠΎ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ ΠΌΡ Π±ΡΠ΄Π΅ΠΌ Π³ΠΎΠ²ΠΎΡΠΈΡΡ ΠΏΠΎΠ·ΠΆΠ΅. ΠΠΎΠΊΠ° ΠΎΡΠΌΠ΅ΡΠΈΠΌ ΡΠΎΠ»ΡΠΊΠΎ, ΡΡΠΎ ΡΠΈΡΠ»ΠΎ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΎΠΊ ΡΡΡΠΎΠΊ Π½ΠΈΡΠ΅ΠΌ Π½Π΅ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΎ. ΠΠ½ΠΈ Π½Π΅ Π·Π°Π½ΠΈΠΌΠ°ΡΡ ΠΌΠ΅ΡΡΠΎ Π² ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΎΠΉ ΠΏΠ°ΠΌΡΡΠΈ ΠΈ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΡ ΡΠΈΡΡΠ΅ΠΌΡ Π½Π΅ ΡΡΡΠ°Π΄Π°Π΅Ρ ΠΎΡ ΠΈΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π°. ΠΡΠ°Π²Π΄Π°, Ρ βΠ΄Π»ΠΈΠ½Π½ΡΡ β ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΉ Π΅ΡΡΡ Π΄ΡΡΠ³ΠΈΠ΅ ΠΌΠΈΠ½ΡΡΡ, Π½ΠΎ ΠΎΠ± ΡΡΠΎΠΌ ΡΠΎΠΆΠ΅ ΠΏΠΎΠ·ΠΆΠ΅.
Π£Π΄Π°Π»ΠΈΠΌ ΡΡΡΠΎΠΊΡ.
=> 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 Π΄Π»Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ Π²ΡΡΡΠ°Π²Π»ΡΠ΅ΡΡΡ Π±ΠΈΡ aborted. ΠΡΠΌΠ΅Π½Π° Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΡΠ°ΠΊ ΠΆΠ΅ Π±ΡΡΡΡΠΎ, ΠΊΠ°ΠΊ ΠΈ ΡΠΈΠΊΡΠ°ΡΠΈΡ. Π₯ΠΎΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Π° ΠΈ Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ 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-Π΄Π΅ΡΠ΅Π²Π° Π΅ΡΡΡ ΡΡΡΠ°Π½ΠΈΡΠ° Ρ ΠΌΠ΅ΡΠ°Π΄Π°Π½Π½ΡΠΌΠΈ ΠΈ Β«ΠΎΠ±ΡΡΠ½ΡΠ΅Β» ΡΡΡΠ°Π½ΠΈΡΡ.
Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅, ΠΎΠ±ΡΡΠ½ΠΎ Π² ΡΡΡΠ°Π½ΠΈΡΠ΅ ΠΈΠΌΠ΅Π΅ΡΡΡ ΠΌΠ°ΡΡΠΈΠ² ΡΠΊΠ°Π·Π°ΡΠ΅Π»Π΅ΠΉ Π½Π° ΡΡΡΠΎΠΊΠΈ ΠΈ ΡΠ°ΠΌΠΈ ΡΡΡΠΎΠΊΠΈ (ΡΠ°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ Π² ΡΠ°Π±Π»ΠΈΡΠ½ΠΎΠΉ ΡΡΡΠ°Π½ΠΈΡΠ΅). ΠΡΠΎΠΌΠ΅ ΡΠΎΠ³ΠΎ, Π² ΠΊΠΎΠ½ΡΠ΅ ΡΡΡΠ°Π½ΠΈΡΡ ΠΎΡΠ²ΠΎΠ΄ΠΈΡΡΡ ΠΌΠ΅ΡΡΠΎ ΠΏΠΎΠ΄ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅.
Π‘ΡΡΠΎΠΊΠΈ Π² ΠΈΠ½Π΄Π΅ΠΊΡΠ°Ρ ΡΠΎΠΆΠ΅ ΠΌΠΎΠ³ΡΡ ΠΈΠΌΠ΅ΡΡ ΠΎΡΠ΅Π½Ρ ΡΠ°Π·Π½ΡΡ ΡΡΡΡΠΊΡΡΡΡ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΡΠΈΠΏΠ° ΠΈΠ½Π΄Π΅ΠΊΡΠ°. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π»Ρ 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 ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΡ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡΡΡ Β«ΡΠΊΠΎΠ½ΠΎΠΌΠΈΡΡΒ» Π½ΠΎΠΌΠ΅ΡΠ° ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΉ.
ΠΡΠ»ΠΈ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΈΡΠ°Π΅Ρ Π΄Π°Π½Π½ΡΠ΅, ΡΠΎ ΠΎΠ½Π° Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ Π²Π»ΠΈΡΠ΅Ρ Π½Π° Π²ΠΈΠ΄ΠΈΠΌΠΎΡΡΡ Π²Π΅ΡΡΠΈΠΉ ΡΡΡΠΎΠΊ. ΠΠΎΡΡΠΎΠΌΡ Π²Π½Π°ΡΠ°Π»Π΅ ΠΎΠ±ΡΠ»ΡΠΆΠΈΠ²Π°ΡΡΠΈΠΉ ΠΏΡΠΎΡΠ΅ΡΡ Π²ΡΠ΄Π°Π΅Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ Π²ΠΈΡΡΡΠ°Π»ΡΠ½ΡΠΉ Π½ΠΎΠΌΠ΅Ρ (virtual 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), ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡΡ ΠΎΡΠΌΠ΅Π½ΠΈΡΡ ΡΠ°ΡΡΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠ΅ΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ, Π½Π΅ ΠΏΡΠ΅ΡΡΠ²Π°Ρ Π΅Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ. ΠΠΎ ΡΡΠΎ Π½Π΅ ΡΠΊΠ»Π°Π΄ΡΠ²Π°Π΅ΡΡΡ Π² ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½Π½ΡΡ Π²ΡΡΠ΅ ΡΡ Π΅ΠΌΡ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΡΠ°ΡΡΡ Ρ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ ΠΎΠ΄ΠΈΠ½ Π½Π° Π²ΡΠ΅ Π΅Π΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ, Π° ΡΠΈΠ·ΠΈΡΠ΅ΡΠΊΠΈ Π½ΠΈΠΊΠ°ΠΊΠΈΠ΅ Π΄Π°Π½Π½ΡΠ΅ Π½Π΅ ΠΎΡΠΊΠ°ΡΡΠ²Π°ΡΡΡΡ.
Π§ΡΠΎΠ±Ρ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΡΠ°ΠΊΠΎΠΉ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π», ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡ Ρ ΡΠΎΡΠΊΠΎΠΉ ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ ΡΠ°Π·Π±ΠΈΠ²Π°Π΅ΡΡΡ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΡ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΡ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΉ (subtransaction), ΡΡΠ°ΡΡΡΠΎΠΌ ΠΊΠΎΡΠΎΡΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΏΡΠ°Π²Π»ΡΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎ.
ΠΠ»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ ΠΈΠΌΠ΅ΡΡ ΡΠ²ΠΎΠΉ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠΉ Π½ΠΎΠΌΠ΅Ρ (Π±Γ³Π»ΡΡΠΈΠΉ, ΡΠ΅ΠΌ Π½ΠΎΠΌΠ΅Ρ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ). Π‘ΡΠ°ΡΡΡ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΡ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΉ Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ ΠΎΠ±ΡΡΠ½ΡΠΌ ΠΎΠ±ΡΠ°Π·ΠΎΠΌ Π² XACT, ΠΎΠ΄Π½Π°ΠΊΠΎ ΡΠΈΠ½Π°Π»ΡΠ½ΡΠΉ ΡΡΠ°ΡΡΡ Π·Π°Π²ΠΈΡΠΈΡ ΠΎΡ ΡΡΠ°ΡΡΡΠ° ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ: Π΅ΡΠ»ΠΈ ΠΎΠ½Π° ΠΎΡΠΌΠ΅Π½Π΅Π½Π°, ΡΠΎ ΠΎΡΠΌΠ΅Π½ΡΡΡΡΡ ΡΠ°ΠΊΠΆΠ΅ ΠΈ Π²ΡΠ΅ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ.
ΠΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ Π²Π»ΠΎΠΆΠ΅Π½Π½ΠΎΡΡΠΈ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΉ Ρ ΡΠ°Π½ΠΈΡΡΡ Π² ΡΠ°ΠΉΠ»Π°Ρ Π² ΠΊΠ°ΡΠ°Π»ΠΎΠ³Π΅ PGDATA/pg_subtrans. ΠΠ±ΡΠ°ΡΠ΅Π½ΠΈΠ΅ ΠΊ ΡΠ°ΠΉΠ»Π°ΠΌ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΡΠ΅ΡΠ΅Π· Π±ΡΡΠ΅ΡΡ Π² ΠΎΠ±ΡΠ΅ΠΉ ΠΏΠ°ΠΌΡΡΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°, ΠΎΡΠ³Π°Π½ΠΈΠ·ΠΎΠ²Π°Π½Π½ΡΠ΅ ΡΠ°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ Π±ΡΡΠ΅ΡΡ XACT.
ΠΠ΅ ΠΏΡΡΠ°ΠΉΡΠ΅ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ ΠΈ Π°Π²ΡΠΎΠ½ΠΎΠΌΠ½ΡΠ΅ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ. ΠΠ²ΡΠΎΠ½ΠΎΠΌΠ½ΡΠ΅ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ Π·Π°Π²ΠΈΡΡΡ Π΄ΡΡΠ³ ΠΎΡ Π΄ΡΡΠ³Π°, Π° Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ β Π·Π°Π²ΠΈΡΡΡ. ΠΠ²ΡΠΎΠ½ΠΎΠΌΠ½ΡΡ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΉ Π² ΠΎΠ±ΡΡΠ½ΠΎΠΌ PostgreSQL Π½Π΅Ρ, ΠΈ, ΠΏΠΎΠΆΠ°Π»ΡΠΉ, ΠΊ Π»ΡΡΡΠ΅ΠΌΡ: ΠΏΠΎ Π΄Π΅Π»Ρ ΠΎΠ½ΠΈ Π½ΡΠΆΠ½Ρ ΠΎΡΠ΅Π½Ρ ΠΈ ΠΎΡΠ΅Π½Ρ ΡΠ΅Π΄ΠΊΠΎ, Π° ΠΈΡ Π½Π°Π»ΠΈΡΠΈΠ΅ Π² Π΄ΡΡΠ³ΠΈΡ Π‘Π£ΠΠ ΠΏΡΠΎΠ²ΠΎΡΠΈΡΡΠ΅Ρ Π·Π»ΠΎΡΠΏΠΎΡΡΠ΅Π±Π»Π΅Π½ΠΈΠ΅, ΠΎΡ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΏΠΎΡΠΎΠΌ Π²ΡΠ΅ ΡΡΡΠ°Π΄Π°ΡΡ.
ΠΡΠΈΡΡΠΈΠΌ ΡΠ°Π±Π»ΠΈΡΡ, Π½Π°ΡΠ½Π΅ΠΌ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΡ ΠΈ Π²ΡΡΠ°Π²ΠΈΠΌ ΡΡΡΠΎΠΊΡ:
=> 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 ΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ ΡΡΠ°Π²ΠΈΡ ΠΏΠ΅ΡΠ΅Π΄ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄ΠΎΠΉ Π½Π΅ΡΠ²Π½ΡΡ ΡΠΎΡΠΊΡ ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ, Π° Π² ΡΠ»ΡΡΠ°Π΅ ΡΠ±ΠΎΡ ΠΈΠ½ΠΈΡΠΈΠΈΡΡΠ΅Ρ ΠΎΡΠΊΠ°Ρ ΠΊ Π½Π΅ΠΉ. Π’Π°ΠΊΠΎΠΉ ΡΠ΅ΠΆΠΈΠΌ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ, ΠΏΠΎΡΠΊΠΎΠ»ΡΠΊΡ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ° ΡΠΎΡΠ΅ΠΊ ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ (Π΄Π°ΠΆΠ΅ Π±Π΅Π· ΠΎΡΠΊΠ°ΡΠ° ΠΊ Π½ΠΈΠΌ) ΡΠΎΠΏΡΡΠΆΠ΅Π½Π° Ρ ΡΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΡΠΌΠΈ Π½Π°ΠΊΠ»Π°Π΄Π½ΡΠΌΠΈ ΡΠ°ΡΡ ΠΎΠ΄Π°ΠΌΠΈ.
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com