MVCC-3. String verżjonijiet

Għalhekk, ikkunsidrajna kwistjonijiet relatati insulazzjoni, u għamel irtir dwar organizzazzjoni tad-data f'livell baxx. U fl-aħħar wasalna għall-aktar parti interessanti - il-verżjonijiet tal-kordi.

Titolu

Kif diġà għedna, kull ringiela tista' teżisti simultanjament f'diversi verżjonijiet fid-database. Verżjoni waħda trid tkun b'xi mod distinta minn oħra Għal dan il-għan, kull verżjoni għandha żewġ marki li jiddeterminaw il-"ħin" ta 'azzjoni ta' din il-verżjoni (xmin u xmax). Fi kwotazzjonijiet - għax mhux iż-żmien bħala tali li jintuża, iżda counter speċjali li qed jiżdied. U dan il-counter huwa n-numru tat-tranżazzjoni.

(Bħas-soltu, ir-realtà hija aktar ikkumplikata: in-numru tat-tranżazzjoni ma jistax jiżdied il-ħin kollu minħabba l-kapaċità limitata tal-bit tal-counter. Iżda aħna se nħarsu lejn dawn id-dettalji fid-dettall meta naslu għall-iffriżar.)

Meta tinħoloq ringiela, xmin jiġi ssettjat għan-numru tat-tranżazzjoni li ħareġ il-kmand INSERT, u xmax jitħalla vojt.

Meta ringiela titħassar, il-valur xmax tal-verżjoni kurrenti huwa mmarkat bin-numru tat-tranżazzjoni li wettqet it-TĦASSIR.

Meta ringiela tiġi modifikata bi kmand AĠĠORNAMENT, fil-fatt jitwettqu żewġ operazzjonijiet: ĦASSAR u Daħħal. Il-verżjoni attwali tar-ringiela tistabbilixxi xmax ugwali għan-numru tat-tranżazzjoni li wettqet l-AĠĠORNAMENT. Imbagħad tinħoloq verżjoni ġdida tal-istess string; il-valur xmin tiegħu jikkoinċidi mal-valur xmax tal-verżjoni preċedenti.

L-oqsma xmin u xmax huma inklużi fl-intestatura tal-verżjoni tar-ringiela. Minbarra dawn l-oqsma, l-intestatura fiha oħrajn, pereżempju:

  • infomask hija serje ta 'bits li jiddefinixxu l-proprjetajiet ta' din il-verżjoni. Hemm pjuttost ħafna minnhom; Se nikkunsidraw gradwalment dawk ewlenin.
  • ctid hija link għall-verżjoni l-ġdida li jmiss tal-istess linja. Għall-verżjoni l-aktar ġdida u attwali ta' string, is-ctid tirreferi għal din il-verżjoni nnifisha. In-numru għandu l-forma (x,y), fejn x huwa n-numru tal-paġna, y huwa n-numru tal-indiċi fil-firxa.
  • null bitmap - Jimmarka dawk il-kolonni ta' verżjoni partikolari li fihom valur null (NULL). NULL mhuwiex wieħed mill-valuri normali tat-tip tad-dejta, għalhekk l-attribut għandu jinħażen separatament.

Bħala riżultat, l-header huwa pjuttost kbir - mill-inqas 23 bytes għal kull verżjoni tal-linja, u ġeneralment aktar minħabba l-bitmap NULL. Jekk it-tabella hija "dejqa" (jiġifieri fiha ftit kolonni), l-overhead jista 'jieħu aktar mill-informazzjoni utli.

daħħal

Ejja nagħtu ħarsa aktar mill-qrib lejn kif jitwettqu operazzjonijiet ta 'korda ta' livell baxx, nibdew bl-inserzjoni.

Għal esperimenti, ejja noħolqu tabella ġdida b'żewġ kolonni u indiċi fuq waħda minnhom:

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

Ejja daħħal ringiela waħda wara li tibda tranżazzjoni.

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

Hawn in-numru tat-tranżazzjoni attwali tagħna:

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

Ejja nħarsu lejn il-kontenut tal-paġna. Il-funzjoni heap_page_items tal-estensjoni pageinspect tippermettilek tikseb informazzjoni dwar indikaturi u verżjonijiet tar-ringieli:

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

Innota li l-kelma borġ f'PostgreSQL tirreferi għal tabelli. Dan huwa użu stramb ieħor tat-terminu - hu magħruf borġ struttura tad-data, li m'għandha xejn komuni mat-tabella. Hawnhekk il-kelma hija użata fis-sens ta '"kollox jintrema flimkien," għall-kuntrarju ta' indiċi ordnati.

Il-funzjoni turi data "kif inhi", f'format li huwa diffiċli biex tinftiehem. Biex insemmu, se nħallu biss parti mill-informazzjoni u niddeċifrawha:

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

Hawn dak li għamilna:

  • Żieda żero man-numru tal-indiċi biex jagħmilha l-istess bħal t_ctid: (numru tal-paġna, numru tal-indiċi).
  • Iddeċifrat l-istat tal-pointer lp_flags. Hawnhekk huwa "normali" - dan ifisser li l-pointer fil-fatt jirreferi għall-verżjoni tas-sekwenza. Inħarsu lejn tifsiriet oħra aktar tard.
  • Mill-bits ta 'informazzjoni kollha, żewġ pari biss ġew identifikati s'issa. Il-bits xmin_committed u xmin_aborted jindikaw jekk in-numru tat-tranżazzjoni xmin huwiex kommess (abort). Żewġ bits simili jirreferu għan-numru tat-tranżazzjoni xmax.

X'naraw? Meta ddaħħal ringiela, se jidher indiċi numru 1 fil-paġna tat-tabella, li jindika l-ewwel u l-unika verżjoni tar-ringiela.

Fil-verżjoni string, il-qasam xmin jimtela bin-numru tat-tranżazzjoni kurrenti. It-tranżazzjoni għadha attiva, għalhekk kemm il-bits xmin_committed u xmin_aborted mhumiex issettjati.

Il-qasam ctid tal-verżjoni tar-ringiela jirreferi għall-istess ringiela. Dan ifisser li ma teżistix verżjoni aktar ġdida.

Il-qasam xmax huwa mimli b'numru finta 0 minħabba li din il-verżjoni tar-ringiela ma ġietx imħassra u hija attwali. It-tranżazzjonijiet mhux se jagħtu attenzjoni għal dan in-numru minħabba li l-bit xmax_aborted huwa ssettjat.

Ejja nieħdu pass ieħor lejn it-titjib tal-leġibbiltà billi żżid bits ta 'informazzjoni man-numri tat-tranżazzjonijiet. U ejja noħolqu funzjoni, peress li se jkollna bżonn it-talba aktar minn darba:

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

F'din il-forma, huwa ħafna aktar ċar x'inhu għaddej fl-intestatura tal-verżjoni tar-ringiela:

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

Informazzjoni simili, iżda b'mod sinifikanti inqas dettaljata, tista' tinkiseb mit-tabella nnifisha, bl-użu tal-psewdokolonni xmin u xmax:

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

Fissazzjoni

Jekk tranżazzjoni titlesta b'suċċess, trid tiftakar l-istatus tagħha - innota li hija impenjata. Biex tagħmel dan, tintuża struttura msejħa XACT (u qabel il-verżjoni 10 kienet tissejjaħ CLOG (commit log) u dan l-isem għadu jista’ jinstab f’postijiet differenti).

XACT mhijiex tabella ta' katalogu tas-sistema; dawn huma l-fajls fid-direttorju PGDATA/pg_xact. Huma għandhom żewġ bits għal kull tranżazzjoni: kommessi u abortiti - bħal fil-header tal-verżjoni ringiela. Din l-informazzjoni hija maqsuma f'diversi fajls biss għall-konvenjenza; se nerġgħu lura għal din il-kwistjoni meta nikkunsidraw l-iffriżar. U x-xogħol ma 'dawn il-fajls jitwettaq paġna b'paġna, bħall-oħrajn kollha.

Għalhekk, meta tranżazzjoni tiġi kommessa f'XACT, il-bit kommess jiġi ssettjat għal din it-tranżazzjoni. U dan huwa dak kollu li jiġri waqt l-impenn (għalkemm għadna mhux qed nitkellmu dwar il-ġurnal ta’ qabel ir-reġistrazzjoni).

Meta tranżazzjoni oħra taċċessa l-paġna tat-tabella li għadna kif ħares lejha, ​​ikollha twieġeb diversi mistoqsijiet.

  1. Tlestiet it-tranżazzjoni xmin? Jekk le, allura l-verżjoni maħluqa tas-sekwenza m'għandhiex tkun viżibbli.
    Din il-verifika titwettaq billi tħares lejn struttura oħra, li tinsab fil-memorja kondiviża tal-istanza u tissejjaħ ProcArray. Fiha lista tal-proċessi attivi kollha, u għal kull wieħed huwa indikat in-numru tat-tranżazzjoni (attiva) attwali tagħha.
  2. Jekk titlesta, allura kif - billi tikkommetti jew tikkanċella? Jekk tiġi kkanċellata, allura l-verżjoni tar-ringiela m'għandhiex tkun viżibbli lanqas.
    Dan huwa eżattament għalxiex XACT. Iżda, għalkemm l-aħħar paġni ta 'XACT huma maħżuna fil-buffers fir-RAM, xorta huwa għali li jiċċekkja XACT kull darba. Għalhekk, ladarba l-istatus tat-tranżazzjoni jiġi ddeterminat, jinkiteb fil-bits xmin_committed u xmin_aborted tal-verżjoni string. Jekk wieħed minn dawn il-bits jiġi ssettjat, allura l-istat tat-tranżazzjoni xmin jitqies magħruf u t-tranżazzjoni li jmiss ma jkollhiex għalfejn taċċessa XACT.

Għaliex dawn il-bits mhumiex stabbiliti mit-tranżazzjoni nnifisha tagħmel l-inserzjoni? Meta sseħħ inserzjoni, it-tranżazzjoni għadha ma tafx jekk tirnexxix. U fil-mument tat-twettiq, m'għadux ċar liema linji f'liema paġni ġew mibdula. Jista 'jkun hemm ħafna paġni bħal dawn, u l-memorizzazzjoni tagħhom ma tagħmilx qligħ. Barra minn hekk, xi paġni jistgħu jiġu żgumbrati mill-cache tal-buffer għal disk; qari minnhom mill-ġdid biex jibdlu l-bits inaqqas il-kommit b'mod sinifikanti.

L-iżvantaġġ tal-iffrankar huwa li wara l-bidliet, kwalunkwe tranżazzjoni (anke waħda li twettaq qari sempliċi - SELECT) tista 'tibda tbiddel il-paġni tad-dejta fil-cache tal-buffer.

Allura, ejja nirranġaw il-bidla.

=> COMMIT;

Xejn ma nbidel fil-paġna (iżda nafu li l-istatus tat-tranżazzjoni huwa diġà rreġistrat f'XACT):

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

Issa t-tranżazzjoni li taċċessa l-paġna l-ewwel trid tiddetermina l-istatus tat-tranżazzjoni xmin u tiktebha fil-bits tal-informazzjoni:

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

Tħassir

Meta ringiela titħassar, in-numru tat-tranżazzjoni kurrenti tat-tħassir jinkiteb fil-qasam xmax tal-verżjoni kurrenti, u l-bit xmax_aborted jitneħħa.

Innota li l-valur stabbilit ta 'xmax li jikkorrispondi għat-tranżazzjoni attiva jaġixxi bħala lock ringiela. Jekk tranżazzjoni oħra trid taġġorna jew tħassar din ir-ringiela, tkun sfurzata tistenna li t-transazzjoni xmax titlesta. Nitkellmu aktar dwar l-imblukkar aktar tard. Għalissa, aħna biss ninnotaw li n-numru ta 'serraturi ringiela huwa illimitat. Ma jieħdux spazju fir-RAM u l-prestazzjoni tas-sistema ma tbatix min-numru tagħhom. Veru, tranżazzjonijiet "twil" għandhom żvantaġġi oħra, iżda aktar dwar dan aktar tard.

Ejja nħassru l-linja.

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

Naraw li n-numru tat-tranżazzjoni huwa miktub fil-qasam xmax, iżda l-bits tal-informazzjoni mhumiex stabbiliti:

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

Kanċellazzjoni

L-abort tal-bidliet jaħdem b'mod simili għall-impenn, biss f'XACT il-bit abort huwa ssettjat għat-tranżazzjoni. It-tneħħija hija mgħaġġla daqs l-impenn. Għalkemm il-kmand huwa msejjaħ ROLLBACK, il-bidliet ma jiġux rrumblati lura: dak kollu li t-tranżazzjoni rnexxielha tibdel fil-paġni tad-dejta jibqa' mhux mibdul.

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

Meta tiġi aċċessata l-paġna, l-istatus jiġi ċċekkjat u l-bit ħjiel xmax_aborted jiġi ssettjat għall-verżjoni ringiela. In-numru xmax innifsu jibqa 'fuq il-paġna, iżda ħadd ma jħares lejh.

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

Aġġornament

L-aġġornament jaħdem bħallikieku l-ewwel ħassar il-verżjoni attwali tar-ringiela u mbagħad daħħal waħda ġdida.

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

Il-mistoqsija tipproduċi linja waħda (verżjoni ġdida):

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

Iżda fil-paġna naraw iż-żewġ verżjonijiet:

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

Il-verżjoni mħassra hija mmarkata bin-numru tat-tranżazzjoni kurrenti fil-qasam xmax. Barra minn hekk, dan il-valur huwa miktub fuq dak l-antik, peress li t-tranżazzjoni preċedenti ġiet ikkanċellata. U l-bit xmax_aborted jitneħħa minħabba li l-istatus tat-tranżazzjoni kurrenti għadu mhux magħruf.

L-ewwel verżjoni tal-linja issa tirreferi għat-tieni (qasam t_ctid) bħala l-aktar waħda ġdida.

It-tieni indiċi jidher fil-paġna tal-indiċi u t-tieni ringiela tirreferi għat-tieni verżjoni fil-paġna tat-tabella.

L-istess bħal mat-tħassir, il-valur xmax fl-ewwel verżjoni tar-ringiela huwa indikazzjoni li r-ringiela hija msakkra.

Ukoll, ejja tlesti t-tranżazzjoni.

=> COMMIT;

Indiċijiet

S'issa tkellimna biss dwar il-paġni tat-tabella. X'jiġri ġewwa l-indiċi?

L-informazzjoni fil-paġni tal-indiċi tvarja ħafna skont it-tip speċifiku tal-indiċi. U anki tip wieħed ta 'indiċi għandu tipi differenti ta' paġni. Pereżempju, siġra B għandha paġna tal-metadejta u paġni "regolari".

Madankollu, il-paġna normalment ikollha firxa ta 'indikazzjonijiet għar-ringieli u r-ringieli nfushom (bħal paġna ta' tabella). Barra minn hekk, fl-aħħar tal-paġna hemm spazju għal data speċjali.

Ringieli fl-indiċi jista 'jkollhom ukoll strutturi differenti ħafna skond it-tip ta' indiċi. Pereżempju, għal siġra B, ir-ringieli relatati mal-paġni tal-weraq fihom il-valur taċ-ċavetta tal-indiċjar u referenza (ctid) għar-ringiela korrispondenti tat-tabella. B'mod ġenerali, l-indiċi jista 'jiġi strutturat b'mod kompletament differenti.

L-iktar punt importanti huwa li m'hemm l-ebda verżjonijiet ta 'ringiela fl-indiċi ta' kwalunkwe tip. Ukoll, jew nistgħu nassumu li kull linja hija rappreżentata eżattament minn verżjoni waħda. Fi kliem ieħor, m'hemm l-ebda oqsma xmin u xmax fl-intestatura tar-ringiela tal-indiċi. Nistgħu nassumu li r-rabtiet mill-indiċi jwasslu għall-verżjonijiet kollha tat-tabella tar-ringieli - sabiex tkun tista' tara liema verżjoni se tara t-tranżazzjoni biss billi tħares lejn it-tabella. (Bħal dejjem, din mhix il-verità kollha. F'xi każijiet, il-mappa tal-viżibilità tista 'tottimizza l-proċess, iżda se nħarsu lejn dan f'aktar dettall aktar tard.)

Fl-istess ħin, fil-paġna tal-indiċi nsibu indikaturi għaż-żewġ verżjonijiet, kemm dik attwali kif ukoll dik l-antika:

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

Tranżazzjonijiet virtwali

Fil-prattika, PostgreSQL juża ottimizzazzjonijiet li jippermettulu li "jiffranka" in-numri tat-tranżazzjonijiet.

Jekk tranżazzjoni taqra d-dejta biss, ma għandha l-ebda effett fuq il-viżibilità tal-verżjonijiet tar-ringiela. Għalhekk, il-proċess tas-servizz l-ewwel joħroġ xid virtwali għat-tranżazzjoni. In-numru jikkonsisti f'ID tal-proċess u numru ta' sekwenza.

Il-ħruġ ta 'dan in-numru ma jeħtieġx sinkronizzazzjoni bejn il-proċessi kollha u għalhekk huwa mgħaġġel ħafna. Se nkunu familjari ma 'raġuni oħra għall-użu ta' numri virtwali meta nitkellmu dwar l-iffriżar.

In-numri virtwali ma jitqiesu bl-ebda mod fl-istampa tad-dejta.

F'mumenti differenti fiż-żmien, jista 'jkun hemm tranżazzjonijiet virtwali fis-sistema b'numri li diġà ntużaw, u dan huwa normali. Iżda numru bħal dan ma jistax jinkiteb fil-paġni tad-dejta, minħabba li l-ħin li jmiss il-paġna tiġi aċċessata tista 'titlef kull tifsira.

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

Jekk tranżazzjoni tibda tbiddel id-dejta, tingħata numru ta’ tranżazzjoni reali u uniku.

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

=> COMMIT;

Tranżazzjonijiet imniżżlin

Ħlief punti

Iddefinit fl-SQL ħlief punti (savepoint), li jippermettulek tikkanċella parti minn tranżazzjoni mingħajr ma tinterrompiha kompletament. Iżda dan ma jidħolx fid-dijagramma ta 'hawn fuq, peress li t-tranżazzjoni għandha l-istess status għall-bidliet kollha tagħha, u fiżikament l-ebda data ma tiġi rritornata.

Biex timplimenta din il-funzjonalità, tranżazzjoni b'punt ta' salvataġġ hija maqsuma f'diversi separati transazzjonijiet nested (subtranżazzjoni), li l-istatus tagħha jista’ jiġi ġestit separatament.

Tranżazzjonijiet imdaħħla għandhom in-numru tagħhom stess (ogħla min-numru tat-tranżazzjoni prinċipali). L-istatus tat-tranżazzjonijiet imnaqqxa huwa rreġistrat bil-mod tas-soltu f'XACT, iżda l-istatus finali jiddependi fuq l-istatus tat-tranżazzjoni prinċipali: jekk tiġi kkanċellata, allura t-tranżazzjonijiet imnaqqsa kollha jiġu kkanċellati wkoll.

Informazzjoni dwar it-tbejjit tat-tranżazzjonijiet hija maħżuna f'fajls fid-direttorju PGDATA/pg_subtrans. Fajls huma aċċessati permezz ta 'buffers fil-memorja kondiviża tal-istanza, organizzati bl-istess mod bħall-buffers XACT.

Tħawwadx it-tranżazzjonijiet nested ma' tranżazzjonijiet awtonomi. Tranżazzjonijiet awtonomi ma jiddependu fuq xulxin bl-ebda mod, iżda tranżazzjonijiet nested jagħmlu. M'hemm l-ebda tranżazzjonijiet awtonomi f'PostgreSQL regolari, u, forsi, għall-aħjar: huma meħtieġa ħafna, rari ħafna, u l-preżenza tagħhom f'DBMSs oħra tipprovoka abbuż, li mbagħad ibati kulħadd.

Ejja naddaf it-tabella, ibda tranżazzjoni u daħħal ir-ringiela:

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

Issa ejja npoġġu punt ta 'salvataġġ u daħħal linja oħra.

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

Innota li l-funzjoni txid_current() tirritorna n-numru tat-tranżazzjoni prinċipali, mhux in-numru tat-tranżazzjoni nested.

=> SELECT xmin, xmax, * FROM t;
 xmin | xmax | id |  s  
------+------+----+-----
 3669 |    0 |  2 | FOO
 3670 |    0 |  3 | XYZ
(2 rows)

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

Ejja nerġgħu lura għall-punt ta 'salvataġġ u daħħal it-tielet linja.

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

Fil-paġna nkomplu naraw ir-ringiela miżjuda bit-tranżazzjoni nested ikkanċellata.

Aħna nirranġaw il-bidliet.

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

Issa tista 'tara b'mod ċar li kull transazzjoni nested għandha l-istatus tagħha stess.

Innota li t-tranżazzjonijiet nested ma jistgħux jintużaw b'mod espliċitu fl-SQL, jiġifieri, ma tistax tibda tranżazzjoni ġdida mingħajr ma tlesti dik attwali. Dan il-mekkaniżmu jiġi attivat b'mod impliċitu meta jintużaw punti ta' salvataġġ, kif ukoll meta jiġu mmaniġġjati eċċezzjonijiet PL/pgSQL u f'numru ta' każijiet oħra, aktar eżotiċi.

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

Żbalji u atomiċità ta' operazzjonijiet

X'jiġri jekk iseħħ żball waqt li tkun qed issir operazzjoni? Per eżempju, bħal dan:

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

Sar żball. Issa t-tranżazzjoni titqies abortita u l-ebda operazzjoni mhi permessa fiha:

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

U anki jekk tipprova tikkommetti l-bidliet, PostgreSQL jirrapporta abort:

=> COMMIT;
ROLLBACK

Għaliex tranżazzjoni ma tistax tkompli wara falliment? Il-fatt hu li żball jista 'jqum b'tali mod li niksbu aċċess għal parti mill-bidliet - l-atomiċità ta' lanqas it-tranżazzjoni, iżda l-operatur ikun miksur. Bħal fl-eżempju tagħna, fejn l-operatur irnexxielu jaġġorna linja waħda qabel l-iżball:

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

Għandu jingħad li psql għandu mod li xorta jippermetti li t-tranżazzjoni tkompli wara falliment bħallikieku l-azzjonijiet ta 'l-operatur żbaljat ġew irrumblati lura.

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

Mhuwiex diffiċli li wieħed raden li f'dan il-mod, psql fil-fatt ipoġġi punt ta 'salvataġġ impliċitu qabel kull kmand, u f'każ ta' falliment jibda rollback għalih. Din il-modalità ma tintużax b'mod awtomatiku, peress li l-issettjar ta' punti ta' salvataġġ (anki mingħajr ma jinqalgħu lura għalihom) jinvolvi overhead sinifikanti.

Kontinwazzjoni.

Sors: www.habr.com

Żid kumment