MVCC-3. Dikan-teny string

Noho izany, nandinika olana mifandraika amin'izany izahay insulation, ary nanao fihemorana fandaminana angon-drakitra amin'ny ambaratonga ambany. Ary farany dia tonga tany amin'ny ampahany mahaliana indrindra - ny dikan-teny.

lohapejy

Araka ny efa voalazanay, ny andalana tsirairay dia afaka miaraka amin'ny dikan-teny maromaro ao amin'ny tahiry. Ny dikan-teny iray dia tsy maintsy avahana amin'ny iray hafa. Mba hanaovana izany, ny dikan-teny tsirairay dia manana marika roa mamaritra ny "fotoana" amin'ity dikan-teny ity (xmin sy xmax). Ao amin'ny teny nalaina - satria tsy fotoana toy izany no ampiasaina, fa ny fitomboana manokana counter. Ary ity kaontera ity no laharan'ny fifampiraharahana.

(Araka ny mahazatra, sarotra kokoa ny zava-misy: tsy afaka mitombo hatrany ny laharan'ny fifampiraharahana noho ny fahafahan'ny kaontera voafetra. Fa hojerentsika amin'ny antsipiriany ireo antsipiriany ireo rehefa tonga any amin'ny hatsiaka isika.)

Rehefa noforonina ny laharana iray, ny xmin dia napetraka amin'ny laharan'ny fifanakalozana izay namoaka ny baiko INSERT, ary ny xmax dia avela ho banga.

Rehefa voafafa ny laharana iray, ny sanda xmax amin'ny dikan-teny ankehitriny dia voamarika amin'ny laharan'ny fifampiraharahana nanao ny DELETE.

Rehefa ovain'ny baiko UPDATE ny laharana iray dia misy asa roa atao: DELETE sy INSERT. Ny dikan-teny ankehitriny amin'ny laharana dia mametraka xmax mitovy amin'ny isan'ny varotra nanao ny UPDATE. Avy eo dia misy dikan-teny vaovao amin'ny tady mitovy; ny sanda xmin dia mifanandrify amin'ny sanda xmax amin'ny dikan-teny teo aloha.

Ny saha xmin sy xmax dia tafiditra ao amin'ny lohatenin'ny tsipika. Ho fanampin'ireo saha ireo, misy hafa ny lohapejy, ohatra:

  • infomask dia andiana bit izay mamaritra ny toetran'ity dikan-teny ity. Tena betsaka izy ireo; Hodinihintsika tsikelikely ny tena zava-dehibe.
  • ctid dia rohy mankany amin'ny dikan-teny manaraka sy vaovao amin'ny andalana mitovy. Ho an'ny kinova farany indrindra amin'ny tsipika iray, ny ctid dia manondro an'io dikan-teny io. Ny isa dia manana endrika (x,y), izay x ny laharan'ny pejy, y ny laharan'ny fanondro ao amin'ny laharan-kira.
  • null bitmap - Manamarika ireo tsanganana amin'ny dikan-teny nomena izay misy sanda null (NULL). NULL dia tsy iray amin'ireo soatoavina karazana data mahazatra, noho izany dia tsy maintsy tehirizina misaraka ny toetra.

Vokatr'izany dia lehibe ny lohateniny - farafaharatsiny 23 bytes ho an'ny dikan-teny tsirairay, ary matetika kokoa noho ny bitmap NULL. Raha "ety" ny latabatra (izany hoe, misy tsanganana vitsivitsy), ny ambony dia mety haka mihoatra noho ny fampahalalana mahasoa.

Mampidira

Andeha hojerentsika akaiky ny fomba fiasan'ny tady ambany, manomboka amin'ny fampidirana.

Ho an'ny fanandramana, andao hamorona latabatra vaovao misy tsanganana roa sy tondro amin'ny iray amin'izy ireo:

=> CREATE TABLE t(
  id serial,
  s text
);
=> CREATE INDEX ON t(s);

Andeha ampidiro andalana iray aorian'ny fanombohana fifampiraharahana.

=> BEGIN;
=> INSERT INTO t(s) VALUES ('FOO');

Ity ny laharan'ny fifampiraharahana amin'izao fotoana izao:

=> SELECT txid_current();
 txid_current 
--------------
         3664
(1 row)

Andeha hojerentsika ny votoatin'ny pejy. Ny fiasan'ny heap_page_items amin'ny fanitarana pageinspect dia ahafahanao mahazo fampahalalana momba ny tondro sy ny dikan-tsipika:

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

Mariho fa ny teny hoe heap ao amin'ny PostgreSQL dia manondro tabilao. Fampiasana hafahafa hafa amin'ny teny izany - misy antontam-baovao fantatra rafitra angona, izay tsy misy ifandraisany amin'ny latabatra. Eto ny teny dia ampiasaina amin'ny dikan'ny hoe "atambatra ny zava-drehetra", mifanohitra amin'ny fanondroana voalamina.

Ny fiasa dia mampiseho angon-drakitra "toy ny misy", amin'ny endrika sarotra takarina. Mba hamantarana izany, dia hamela ampahany amin'ny fampahalalana fotsiny izahay ary hamadika azy:

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

Izao no nataonay:

  • Nampiana aotra ny laharan'ny fanondroana mba hitovy amin'ny t_ctid: (laharan'ny pejy, laharan'ny fanondro).
  • Namaha ny toetry ny tondro lp_flags. Ity dia "ara-dalΓ na" - midika izany fa ny fanondro dia manondro ny dikan'ny tady. Hojerentsika ny dikany hafa any aoriana.
  • Amin'ireo bitika fampahalalam-baovao rehetra dia mpivady roa ihany no fantatra hatreto. Ny bits xmin_committed sy xmin_aborted dia manondro raha efa vita (aborted) ny laharan'ny transaction xmin. Ny bits roa mitovy dia manondro ny laharana xmax.

Inona no hitantsika? Rehefa mampiditra andalana ianao dia hiseho eo amin'ny pejin'ny tabilao ny laharana index 1, manondro ny dikan-teny voalohany sy tokana amin'ny laharana.

Ao amin'ny dikan-tsipika, ny saha xmin dia feno ny laharan'ny fifanakalozana ankehitriny. Mbola mavitrika ny fifampiraharahana, ka tsy napetraka ny bits xmin_committed sy xmin_aborted.

Ny saha ctid version andalana dia manondro andalana iray ihany. Midika izany fa tsy misy dikan-teny vaovao.

Ny saha xmax dia feno isa dummy 0 satria tsy voafafa ity dikan-tsipika ity ary misy ankehitriny. Tsy hiraharaha an'io isa io ny fifampiraharahana satria napetraka ny bit xmax_aborted.

Andeha isika hanao dingana iray hafa amin'ny fanatsarana ny fahaiza-mamaky amin'ny alalan'ny fampidirana bits vaovao amin'ny laharan'ny fifanakalozana. Ary andao hamorona fiasa, satria mila ny fangatahana mihoatra ny indray mandeha isika:

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

Amin'ity endrika ity dia mazava kokoa ny zava-mitranga ao amin'ny lohatenin'ny dikan-tsipika:

=> SELECT * FROM heap_page('t',0);
 ctid  | state  | xmin | xmax  | t_ctid 
-------+--------+------+-------+--------
 (0,1) | normal | 3664 | 0 (a) | (0,1)
(1 row)

Mitovitovy, saingy tsy dia misy antsipiriany loatra, azo alaina avy amin'ny latabatra mihitsy, amin'ny fampiasana pseudo-columns xmin sy xmax:

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

Fixation

Raha toa ka vita soa aman-tsara ny fifampiraharahana, dia mila mitadidy ny toerana misy azy - mariho fa vita izany. Mba hanaovana izany dia ampiasaina ny rafitra antsoina hoe XACT (ary talohan'ny version 10 dia nantsoina hoe CLOG (commit log) ary mbola hita any amin'ny toerana samihafa io anarana io).

XACT dia tsy tabilao katalaogy rafitra; ireto ny rakitra ao amin'ny lahatahiry PGDATA/pg_xact. Manana bitika roa izy ireo ho an'ny fifampiraharahana tsirairay: natao ary nesorina - toy ny ao amin'ny lohatenin'ny tsipika. Ity fampahalalana ity dia zaraina amin'ny rakitra maromaro mba hanamora fotsiny; hiverina amin'ity olana ity isika rehefa mieritreritra ny hivaingana. Ary ny asa miaraka amin'ireo rakitra ireo dia tanterahina isan-pejy, toy ny amin'ny hafa rehetra.

Noho izany, rehefa misy fifampiraharahana atao ao amin'ny XACT, dia napetraka ho an'ity fifampiraharahana ity ny bitika natao. Ary izany ihany no mitranga mandritra ny fanolorana (na dia tsy miresaka momba ny lozisialy mialoha ny firaketana aza isika).

Rehefa miditra amin'ny pejin'ny latabatra vao nojerentsika ny fifampiraharahana hafa dia tsy maintsy mamaly fanontaniana maromaro izy io.

  1. Efa vita ve ny fifampiraharahana xmin? Raha tsy izany dia tsy tokony ho hita ny dikan-teny noforonina.
    Ity fisavana ity dia atao amin'ny fijerena rafitra iray hafa, izay hita ao amin'ny fahatsiarovana iraisan'ny ohatra ary antsoina hoe ProcArray. Ahitana lisitr'ireo dingana mavitrika rehetra izy io, ary ho an'ny tsirairay dia aseho ny isan'ny fifanakalozana ankehitriny (mavitrika).
  2. Raha vita, dia ahoana - amin'ny fanolorana na fanafoanana? Raha nofoanana, dia tsy tokony ho hita koa ny kinova andalana.
    Izany indrindra no anton'ny XACT. Saingy, na dia voatahiry ao anaty buffer ao amin'ny RAM aza ny pejy farany amin'ny XACT, dia mbola lafo ny manamarina ny XACT isaky ny mandeha. Noho izany, rehefa voafaritra ny satan'ny fifampiraharahana, dia soratana amin'ny bits xmin_committed sy xmin_aborted amin'ny version string. Raha apetraka ny iray amin'ireo bits ireo, dia heverina ho fantatra ny toetry ny transaction xmin ary tsy mila miditra amin'ny XACT ny fifampiraharahana manaraka.

Nahoana no tsy ireo bits ireo no napetraky ny transaction mihitsy manao ny insert? Rehefa misy fampidirana dia tsy mbola fantatry ny fifampiraharahana raha hahomby izany. Ary amin'izao fotoana izao dia tsy mazava intsony hoe iza amin'ireo pejy no niova. Mety ho be dia be ny pejy toy izany, ary ny fitadidiana azy ireo dia tsy mahasoa. Fanampin'izany, ny pejy sasany dia azo esorina amin'ny cache buffer mankany amin'ny kapila; Ny famakiana azy ireo indray mba hanovana ny bits dia hampiadana be ny commit.

Ny tsy fahampian'ny tahiry dia ny hoe aorian'ny fanovana, ny fifampiraharahana rehetra (na dia manao vakiteny tsotra aza - SELECT) dia afaka manomboka manova pejy data ao amin'ny cache buffer.

Andeha Γ ry hamboarintsika ny fiovana.

=> COMMIT;

Tsy nisy fiovana teo amin'ny pejy (fa fantatray fa efa voarakitra ao amin'ny XACT ny satan'ny fifanakalozana):

=> SELECT * FROM heap_page('t',0);
 ctid  | state  | xmin | xmax  | t_ctid 
-------+--------+------+-------+--------
 (0,1) | normal | 3664 | 0 (a) | (0,1)
(1 row)

Ankehitriny ny fifampiraharahana izay miditra amin'ny pejy voalohany dia tsy maintsy mamaritra ny satan'ny fifanakalozana xmin ary manoratra izany amin'ny bitika fampahalalana:

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

fanesorana

Rehefa voafafa ny laharana iray, dia soratana amin'ny saha xmax amin'ny dikan-teny ankehitriny ny laharan'ny fifampiraharahana famafana ankehitriny, ary voafafa ny bit xmax_aborted.

Mariho fa ny sandan'ny xmax mifandraika amin'ny fifampiraharahana mavitrika dia miasa toy ny hidin-dΓ lana. Raha misy fifampiraharahana hafa te hanavao na hamafa ity andalana ity, dia voatery miandry ny transaction xmax ho vita. Hiresaka bebe kokoa momba ny fanakanana isika any aoriana. Amin'izao fotoana izao, marihina fotsiny fa tsy voafetra ny isan'ny hidin'ny andalana. Tsy maka toerana ao amin'ny RAM izy ireo ary tsy mijaly amin'ny isany ny fahombiazan'ny rafitra. Marina fa misy fatiantoka hafa ny fifampiraharahana "lava", fa bebe kokoa amin'izany any aoriana.

Andeha hofafana ny tsipika.

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

Hitantsika fa voasoratra ao amin'ny saha xmax ny laharan'ny fifampiraharahana, saingy tsy napetraka ny bitika fampahalalana:

=> SELECT * FROM heap_page('t',0);
 ctid  | state  |   xmin   | xmax | t_ctid 
-------+--------+----------+------+--------
 (0,1) | normal | 3664 (c) | 3665 | (0,1)
(1 row)

fanafoanana

Miasa mitovy amin'ny fanaovana commit ny fanovana fanalana zaza, ao amin'ny XACT ihany no apetraka ho an'ny fifampiraharahana. Ny fanafoanana dia haingana toy ny manolo-tena. Na dia antsoina hoe ROLLBACK aza ny baiko, dia tsy averina ny fanovana: tsy miova ny zavatra rehetra vitan'ny fifanakalozana tamin'ny pejy data.

=> ROLLBACK;
=> SELECT * FROM heap_page('t',0);
 ctid  | state  |   xmin   | xmax | t_ctid 
-------+--------+----------+------+--------
 (0,1) | normal | 3664 (c) | 3665 | (0,1)
(1 row)

Rehefa idirana ny pejy dia hojerena ny sata ary hapetraka amin'ny version row ny bitin'ny xmax_aborted. Ny isa xmax mihitsy no mijanona ao amin'ny pejy, fa tsy misy mijery azy.

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

vaovao farany

Ny fanavaozam-baovao dia miasa toy ny hoe nofafany aloha ny dikan-teny ankehitriny amin'ny laharana ary avy eo nampiditra iray vaovao.

=> BEGIN;
=> UPDATE t SET s = 'BAR';
=> SELECT txid_current();
 txid_current 
--------------
         3666
(1 row)

Mamokatra andalana iray ny fangatahana (vaovao):

=> SELECT * FROM t;
 id |  s  
----+-----
  1 | BAR
(1 row)

Fa amin'ny pejy dia mahita dikan-teny roa isika:

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

Ny dikan-teny voafafa dia voamarika amin'ny laharan'ny fifanakalozana ankehitriny ao amin'ny saha xmax. Ankoatra izany, io sanda io dia nosoratana tamin'ny taloha, satria nofoanana ny varotra teo aloha. Ary ny bit xmax_aborted dia voafafa satria tsy mbola fantatra ny satan'ny transaction ankehitriny.

Ny dikan-teny voalohany amin'ny tsipika izao dia manondro ny faharoa (saha t_ctid) ho ilay vaovao.

Misy tondro faharoa miseho eo amin'ny pejin'ny fanondro ary ny andalana faharoa dia manondro ny dikan-teny faharoa ao amin'ny pejin'ny tabilao.

Tahaka ny amin'ny famafana, ny sanda xmax amin'ny dikan-teny voalohany amin'ny laharana dia manondro fa mihidy ny laharana.

Eny ary, andao hamita ny fifampiraharahana.

=> COMMIT;

fanondroana

Pejy latabatra ihany no resahinay hatreto. Inona no mitranga ao anatin'ireo indexes?

Ny fampahalalana ao amin'ny pejy fanondroana dia miovaova be arakaraka ny karazana fanondroana manokana. Ary na dia karazana fanondroana iray aza dia manana karazana pejy samihafa. Ohatra, ny B-tree dia manana pejy metadata sy pejy "mahazatra".

Na izany aza, matetika ny pejy dia manana tondro maromaro mankany amin'ny andalana sy ny andalana (toy ny pejy tabilao). Ankoatra izany, amin'ny faran'ny pejy dia misy toerana ho an'ny angona manokana.

Ny andalana amin'ny fanondroana dia mety manana rafitra tena samy hafa arakaraka ny karazana fanondroana. Ohatra, ho an'ny hazo B, ny andalana mifandraika amin'ny pejin'ny raviny dia misy ny sanda fanalahidin'ny fanondroana sy fanondroana (ctid) amin'ny laharana latabatra mifanandrify. Amin'ny ankapobeny, ny index dia azo amboarina amin'ny fomba hafa tanteraka.

Ny teboka manan-danja indrindra dia ny tsy fisian'ny dikan-teny andalana amin'ny index na karazana. Eny, na azontsika atao ny mihevitra fa ny andalana tsirairay dia aseho amin'ny dikan-teny iray. Raha lazaina amin'ny teny hafa dia tsy misy saha xmin sy xmax ao amin'ny lohatenin'ny laharana index. Azontsika atao ny mihevitra fa ny rohy avy amin'ny index dia mitondra mankany amin'ny dikan-databatra rehetra amin'ny andalana - ka azonao atao ny mamantatra hoe iza no dikan'ny fifampiraharahana raha tsy mijery ny latabatra. (Araka ny mahazatra, tsy izany no fahamarinana manontolo. Amin'ny toe-javatra sasany, ny sarintany fahitana dia afaka manatsara ny fizotrany, saingy hojerentsika amin'ny antsipiriany bebe kokoa izany any aoriana.)

Amin'izay fotoana izay ihany koa, ao amin'ny pejy fanondroana dia mahita tondro ho an'ny dikan-teny roa, na ny ankehitriny na ny taloha:

=> SELECT itemoffset, ctid FROM bt_page_items('t_s_idx',1);
 itemoffset | ctid  
------------+-------
          1 | (0,2)
          2 | (0,1)
(2 rows)

Transakta virtoaly

Amin'ny fampiharana, ny PostgreSQL dia mampiasa optimizations izay mamela azy "mitahiry" ny isa fifanakalozana.

Raha mamaky angon-drakitra fotsiny ny fifampiraharahana, dia tsy misy fiantraikany amin'ny fahitana ny dikan-teny andalana izany. Noho izany, ny fizotran'ny serivisy dia mamoaka xid virtoaly voalohany amin'ny fifanakalozana. Ny isa dia misy ID dingana sy laharan'ny filaharana.

Ny famoahana io isa io dia tsy mitaky fampifanarahana eo amin'ny dingana rehetra ary noho izany dia tena haingana. Hahafantatra antony hafa hampiasana isa virtoaly isika rehefa miresaka momba ny hatsiaka.

Ny isa virtoaly dia tsy raisina amin'ny fomba rehetra amin'ny snapshots data.

Amin'ny fotoana samihafa dia mety hisy ny fifampiraharahana virtoaly ao amin'ny rafitra misy isa efa nampiasaina, ary ara-dalΓ na izany. Saingy ny isa toy izany dia tsy azo soratana amin'ny pejin'ny data, satria amin'ny fotoana manaraka ny pejy dia mety ho very ny dikany.

=> BEGIN;
=> SELECT txid_current_if_assigned();
 txid_current_if_assigned 
--------------------------
                         
(1 row)

Raha manomboka manova angon-drakitra ny fifampiraharahana, dia omena isa tena izy, tsy manam-paharoa.

=> UPDATE accounts SET amount = amount - 1.00;
=> SELECT txid_current_if_assigned();
 txid_current_if_assigned 
--------------------------
                     3667
(1 row)

=> COMMIT;

Transactions Nested

Tehirizo isa

Voafaritra ao amin'ny SQL mitahiry teboka (savepoint), izay ahafahanao manafoana ampahany amin'ny fifampiraharahana nefa tsy manapaka azy tanteraka. Saingy tsy mifanaraka amin'ny kisary etsy ambony izany, satria mitovy ny sata momba ny fiovany rehetra ny fifanakalozana, ary tsy misy angon-drakitra naverina naverina.

Mba hampiharana an'io fampiasa io dia zaraina misaraka maromaro ny fifampiraharahana miaraka amin'ny savepoint fifampiraharahana nested (subtransaction), ny sata dia azo fehezina mitokana.

Manana ny isany manokana ny fifampiraharahana voatokana (ambony noho ny isan'ny fifampiraharahana lehibe). Voarakitra amin'ny fomba mahazatra ao amin'ny XACT ny satan'ny fifampiraharahana amin'ny akany, fa ny sata farany dia miankina amin'ny satan'ny fifampiraharahana lehibe: raha nofoanana izany, dia hofoanana koa ny fifampiraharahana rehetra.

Ny fampahalalana momba ny fanatobiana ara-barotra dia voatahiry ao anaty rakitra ao amin'ny lahatahiry PGDATA/pg_subtrans. Ny rakitra dia idirana amin'ny alΓ lan'ny buffers ao amin'ny fahatsiarovana iombonan'ny ohatra, voalamina amin'ny fomba mitovy amin'ny XACT buffers.

Aza afangaro amin'ny fifampiraharahana tsy miankina ny fifampiraharaham-pananana. Tsy miankina amin'ny fomba rehetra ny fifampiraharahana tsy miankina, fa ny fifampiraharahana amin'ny nested. Tsy misy fifampiraharahana tsy miankina amin'ny PostgreSQL mahazatra, ary, angamba, ho an'ny tsara indrindra: tena ilaina izy ireo, tena mahalana, ary ny fisian'izy ireo amin'ny DBMS hafa dia miteraka fanararaotana, izay iharan'ny rehetra.

Andeha hodiovina ny latabatra, manomboka fifampiraharahana ary ampidiro ny laharana:

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

Andeha isika hametraka teboka iray ary hampiditra tsipika hafa.

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

Mariho fa ny nxid_current() dia mamerina ny laharan'ny fifanakalozana lehibe, fa tsy ny laharan'ny fifanakalozana.

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

Andao hiverina any amin'ny teboka mitahiry ary ampidiro ny andalana fahatelo.

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

Ao amin'ny pejy dia manohy mahita ny andalana nampidirin'ny fifanakalozana nested nofoanana.

Manamboatra ny fanovana izahay.

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

Hitanao mazava tsara izao fa samy manana ny satany manokana ny fifampiraharahana nested tsirairay.

Mariho fa tsy azo ampiasaina mazava tsara ao amin'ny SQL ny fifampiraharahana amin'ny nested, izany hoe tsy afaka manomboka raharaham-barotra vaovao ianao raha tsy vita ny ankehitriny. Ity mekanika ity dia mihetsika an-kolaka rehefa mampiasa savepoints, ary koa amin'ny fikarakarana PL/pgSQL exceptions ary amin'ny tranga hafa hafahafa kokoa.

=> BEGIN;
BEGIN
=> BEGIN;
WARNING:  there is already a transaction in progress
BEGIN
=> COMMIT;
COMMIT
=> COMMIT;
WARNING:  there is no transaction in progress
COMMIT

Errors sy atomicity ny asa

Inona no mitranga raha misy hadisoana rehefa manao fandidiana? Ohatra, toy izao:

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

Nisy hadisoana nitranga. Amin'izao fotoana izao dia heverina ho tapaka ny fifampiraharahana ary tsy azo atao ny miasa ao:

=> SELECT * FROM t;
ERROR:  current transaction is aborted, commands ignored until end of transaction block

Ary na dia miezaka manao ny fanovana aza ianao, PostgreSQL dia hitatitra fanafoanana:

=> COMMIT;
ROLLBACK

Nahoana no tsy afaka mitohy ny fifampiraharahana aorian'ny tsy fahombiazana? Ny zava-misy dia mety hipoitra ny hadisoana amin'ny fomba ahafahantsika miditra amin'ny ampahany amin'ny fanovana - ny atomika na dia tsy ny fifampiraharahana aza, fa ho voahitsakitsaka ny mpandraharaha. Toy ny amin'ny ohatra asehontsika, izay nahavita nanavao andalana iray talohan'ny fahadisoana ny operatera:

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

Tsy maintsy lazaina fa ny psql dia manana fomba izay mbola mamela ny fifampiraharahana hitohy aorian'ny tsy fahombiazana toy ny hoe naverina indray ny hetsika nataon'ilay mpandraharaha diso.

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

Tsy sarotra ny maminavina fa amin'ity fomba ity, ny psql dia mametraka teboka mitahiry implicit alohan'ny baiko tsirairay, ary raha misy tsy fahombiazana dia manomboka mamerina azy io. Ity fomba ity dia tsy ampiasaina amin'ny alΓ lan'ny default, satria ny fametrahana ny toerana fitehirizana (na dia tsy miverina amin'izy ireo aza) dia mitaky vola be.

Fitohizana.

Source: www.habr.com

Add a comment