MVCC-3. Mga bersyon sa string

Busa, among gikonsiderar ang mga isyu nga may kalabutan sa pagbulag, ug mi-atras sa palibot pag-organisar sa datos sa ubos nga lebel. Ug sa katapusan nakaabut kami sa labing makapaikag nga bahin - ang mga bersyon sa hilo.

Pangulo

Sama sa giingon na namo, ang matag laray mahimong dungan nga anaa sa daghang mga bersyon sa database. Ang usa ka bersyon kinahanglan nga lahi sa lain. Alang niini nga katuyoan, ang matag bersyon adunay duha ka marka nga nagtino sa "panahon" sa paglihok niini nga bersyon (xmin ug xmax). Sa mga kinutlo - tungod kay dili kini panahon sa ingon nga gigamit, apan usa ka espesyal nga pagtaas sa counter. Ug kini nga counter mao ang numero sa transaksyon.

(Sama sa naandan, ang reyalidad mas komplikado: ang numero sa transaksyon dili madugangan sa tanang panahon tungod sa limitadong gamay nga kapasidad sa counter. Apan atong tan-awonon kini nga mga detalye sa detalye inig-abot na nato sa pagyelo.)

Kung ang usa ka laray gihimo, ang xmin gibutang sa numero sa transaksyon nga nag-isyu sa INSERT nga mando, ug ang xmax gibiyaan nga blangko.

Kung ang usa ka laray matangtang, ang xmax nga kantidad sa karon nga bersyon gimarkahan sa numero sa transaksyon nga nagpahigayon sa DELETE.

Kung ang usa ka laray giusab pinaagi sa usa ka UPDATE nga sugo, duha ka mga operasyon ang aktuwal nga gihimo: DELETE ug INSERT. Ang kasamtangan nga bersyon sa row nagtakda sa xmax nga katumbas sa gidaghanon sa transaksyon nga nagpahigayon sa UPDATE. Usa ka bag-ong bersyon sa parehas nga hilo gihimo dayon; ang xmin nga kantidad niini nahiuyon sa xmax nga kantidad sa miaging bersyon.

Ang xmin ug xmax nga mga natad gilakip sa row version header. Dugang pa niini nga mga natad, ang ulohan adunay uban pa, pananglitan:

  • Ang infomask usa ka serye sa mga piraso nga nagpaila sa mga kabtangan niini nga bersyon. Adunay daghan kanila; Atong anam-anam nga tagdon ang mga nag-una.
  • Ang ctid usa ka sumpay sa sunod, mas bag-ong bersyon sa samang linya. Alang sa pinakabag-o, pinakabag-o nga bersyon sa usa ka hilo, ang ctid nagtumong niini nga bersyon mismo. Ang numero adunay porma (x,y), diin x ang numero sa panid, y ang indeks nga numero sa array.
  • null bitmap - Nagmarka sa mga kolum sa gihatag nga bersyon nga adunay null nga kantidad (NULL). Ang NULL dili usa sa normal nga mga kantidad sa tipo sa datos, busa ang hiyas kinahanglan tipigan nga gilain.

Ingon nga resulta, ang header dako kaayo - labing menos 23 ka bytes alang sa matag bersyon sa linya, ug kasagaran mas daghan tungod sa NULL bitmap. Kung ang lamesa "hiktin" (sa ato pa, adunay pipila nga mga kolum), ang overhead mahimong mokuha labi pa sa mapuslanon nga kasayuran.

sal-ot

Atong tan-awon pag-ayo kung giunsa gihimo ang mga operasyon sa ubos nga lebel, sugod sa pagsal-ot.

Para sa mga eksperimento, maghimo ta ug bag-ong lamesa nga adunay duha ka kolum ug indeks sa usa niini:

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

Atong isulod ang usa ka laray human magsugod ug transaksyon.

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

Ania ang among kasamtangan nga numero sa transaksyon:

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

Atong tan-awon ang sulod sa panid. Ang heap_page_items function sa pageinspect extension nagtugot kanimo nga makakuha og impormasyon bahin sa mga pointer ug row versions:

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

Timan-i nga ang pulong heap sa PostgreSQL nagtumong sa mga lamesa. Kini usa pa ka katingad-an nga paggamit sa termino - nahibal-an ang usa ka tapok istruktura sa datos, nga walay kaparehas sa lamesa. Dinhi ang pulong gigamit sa diwa nga "ang tanan gihugpong," sukwahi sa gimando nga mga indeks.

Ang function nagpakita sa data "as is", sa usa ka format nga lisud sabton. Aron mahibal-an kini, ibilin ra namon ang bahin sa kasayuran ug mahibal-an kini:

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

Ania ang among gibuhat:

  • Gidugangan ug sero ang numero sa indeks aron kini tan-awon sama sa t_ctid: (numero sa panid, numero sa indeks).
  • Gi-decipher ang kahimtang sa lp_flags pointer. Dinhi kini "normal" - kini nagpasabut nga ang pointer sa tinuud nagtumong sa bersyon sa hilo. Atong tan-awon ang ubang mga kahulogan sa ulahi.
  • Sa tanan nga mga piraso sa kasayuran, duha ra ka pares ang nahibal-an hangtod karon. Ang xmin_committed ug xmin_aborted bits nagpakita kung ang numero sa transaksyon nga xmin nahimo (aborted). Duha ka parehas nga mga bit ang nagtumong sa numero sa transaksyon nga xmax.

Unsay atong makita? Kung magsal-ot ka og usa ka laray, usa ka indeks nga numero 1 ang makita sa panid sa lamesa, nga magtudlo sa una ug bugtong nga bersyon sa laray.

Sa string nga bersyon, ang xmin field napuno sa kasamtangan nga numero sa transaksyon. Aktibo gihapon ang transaksyon, mao nga ang xmin_committed ug xmin_aborted bits wala gitakda.

Ang row version ctid field nagtumong sa parehas nga row. Kini nagpasabot nga ang mas bag-ong bersyon wala na.

Ang xmax natad napuno sa usa ka dummy nga numero 0 tungod kay kini nga bersyon sa laray wala matangtang ug karon. Ang mga transaksyon dili magtagad niini nga numero tungod kay ang xmax_aborted bit gitakda.

Maghimo kita ug usa pa ka lakang padulong sa pagpauswag sa pagkabasa pinaagi sa pagdugang sa mga piraso sa impormasyon sa mga numero sa transaksyon. Ug maghimo kita usa ka function, tungod kay kinahanglan naton ang hangyo labaw pa sa kausa:

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

Niini nga porma, mas klaro kung unsa ang nahitabo sa ulohan sa bersyon sa linya:

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

Susama, apan dili kaayo detalyado, ang impormasyon mahimong makuha gikan sa lamesa mismo, gamit ang pseudo-columns xmin ug xmax:

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

Pag-ayo

Kung ang usa ka transaksyon malampuson nga nahuman, kinahanglan nimo nga hinumdoman ang kahimtang niini - timan-i nga kini nahimo. Aron mahimo kini, usa ka istruktura nga gitawag og XACT ang gigamit (ug sa wala pa ang bersyon 10 gitawag kini nga CLOG (commit log) ug kini nga ngalan makita gihapon sa lainlaing mga lugar).

Ang XACT dili usa ka lamesa sa katalogo sa sistema; kini ang mga file sa PGDATA/pg_xact nga direktoryo. Adunay sila duha ka piraso alang sa matag transaksyon: gi-commit ug gi-abort - sama sa header sa bersyon sa linya. Kini nga impormasyon gibahin ngadto sa pipila ka mga file para lamang sa kasayon; kita mobalik niini nga isyu sa diha nga kita maghunahuna sa pagyelo. Ug ang pagtrabaho sa kini nga mga file gihimo sa panid matag panid, sama sa uban pa.

Busa, kung ang usa ka transaksyon nahimo sa XACT, ang nahimo nga gamay gitakda alang niini nga transaksyon. Ug kini ang tanan nga mahitabo sa panahon sa paghimo (bisan kung wala pa kami maghisgot bahin sa pre-recording log).

Kung ang lain nga transaksyon maka-access sa panid sa lamesa nga bag-o lang namon gitan-aw, kinahanglan nga tubagon ang daghang mga pangutana.

  1. Nakompleto ba ang transaksyon sa xmin? Kung dili, nan ang gibuhat nga bersyon sa hilo kinahanglan dili makita.
    Kini nga pagsusi gihimo pinaagi sa pagtan-aw sa lain nga istruktura, nga nahimutang sa gipaambit nga panumduman sa pananglitan ug gitawag nga ProcArray. Naglangkob kini sa usa ka lista sa tanan nga mga aktibo nga proseso, ug alang sa matag usa ang gidaghanon sa karon (aktibo) nga transaksyon gipakita.
  2. Kung nahuman, nan unsaon - pinaagi sa pagpasalig o pagkansela? Kung kanselahon, nan ang bersyon sa linya dili usab makita.
    Kini gyud ang para sa XACT. Apan, bisan kung ang katapusang mga panid sa XACT gitipigan sa mga buffer sa RAM, mahal gihapon ang pagsusi sa XACT matag higayon. Busa, sa higayon nga matino ang kahimtang sa transaksyon, kini gisulat sa xmin_committed ug xmin_aborted bits sa string nga bersyon. Kung ang usa niini nga mga piraso gitakda, nan ang kahimtang sa transaksyon xmin giisip nga nahibal-an ug ang sunod nga transaksyon dili kinahanglan nga maka-access sa XACT.

Ngano nga kini nga mga tipik wala gitakda sa transaksyon mismo nga naghimo sa insert? Kung adunay insert nga mahitabo, ang transaksyon wala pa mahibal-an kung kini molampos. Ug sa higayon nga mopasalig, dili na klaro kung unsang mga linya diin ang mga panid giusab. Tingali adunay daghang ingon nga mga panid, ug ang pagsag-ulo niini dili mapuslanon. Dugang pa, ang pipila ka mga panid mahimong mapapahawa gikan sa buffer cache ngadto sa disk; Ang pagbasa niini pag-usab aron mausab ang mga piraso makapahinay pag-ayo sa commit.

Ang downside sa mga savings mao nga human sa mga kausaban, bisan unsa nga transaksyon (bisan ang usa nga naghimo sa usa ka yano nga pagbasa - PILI) mahimong magsugod sa pag-usab sa mga pahina sa data sa buffer cache.

Busa, ayohon nato ang pagbag-o.

=> COMMIT;

Wala’y nabag-o sa panid (apan nahibal-an namon nga ang kahimtang sa transaksyon natala na sa XACT):

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

Karon ang transaksyon nga maka-access sa panid una kinahanglan nga mahibal-an ang kahimtang sa transaksyon sa xmin ug isulat kini sa mga piraso sa impormasyon:

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

Pagtangtang

Kung ang usa ka laray mapapas, ang gidaghanon sa kasamtangan nga pagtangtang sa transaksyon isulat sa xmax field sa kasamtangan nga bersyon, ug ang xmax_aborted bit matangtang.

Timan-i nga ang gitakda nga kantidad sa xmax nga katumbas sa aktibo nga transaksyon naglihok ingon usa ka lock sa laray. Kung gusto sa laing transaksyon nga i-update o i-delete kini nga laray, mapugos kini sa paghulat nga makompleto ang transaksyon xmax. Maghisgot pa kami bahin sa pag-block sa ulahi. Sa pagkakaron, namatikdan lang namo nga ang gidaghanon sa mga lock sa laray walay limitasyon. Wala sila magkuha og luna sa RAM ug ang performance sa sistema wala mag-antos sa ilang numero. Tinuod, ang "dugay" nga mga transaksyon adunay ubang mga disbentaha, apan labaw pa niana sa ulahi.

Atong tangtangon ang linya.

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

Nakita namon nga ang numero sa transaksyon gisulat sa xmax field, apan ang impormasyon nga mga bit wala gitakda:

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

pagkansela

Ang pag-abort sa mga pagbag-o molihok nga parehas sa paghimo, sa XACT ra ang gi-abort nga gamay gitakda alang sa transaksyon. Ang pag-undo dali ra sama sa pagpasalig. Bisan kung ang mando gitawag nga ROLLBACK, ang mga pagbag-o wala gibalikbalik: ang tanan nga nabag-o sa transaksyon sa mga panid sa datos nagpabilin nga wala mausab.

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

Sa diha nga ang panid ma-access, ang status pagasusihon ug ang xmax_aborted nga hint bit ibutang sa row version. Ang xmax nga numero mismo nagpabilin sa panid, apan walay usa nga motan-aw niini.

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

Pag-update

Ang pag-update naglihok ingon nga kini una nga nagtangtang sa kasamtangan nga bersyon sa laray ug dayon gisal-ot ang usa ka bag-o.

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

Ang pangutana nagpatunghag usa ka linya (bag-ong bersyon):

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

Apan sa panid atong makita ang duha ka bersyon:

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

Ang natangtang nga bersyon gimarkahan sa kasamtangan nga numero sa transaksyon sa xmax field. Dugang pa, kini nga kantidad gisulat sa karaan, tungod kay ang miaging transaksyon gikansela. Ug ang xmax_aborted bit gilimpyohan tungod kay ang status sa kasamtangan nga transaksyon wala pa mahibal-an.

Ang unang bersyon sa linya karon nagtumong sa ikaduha (t_ctid field) isip mas bag-o.

Ang ikaduhang index makita sa index page ug ang ikaduhang laray nag-refer sa ikaduhang bersyon sa table page.

Sama sa pagtangtang, ang xmax nga kantidad sa una nga bersyon sa linya usa ka timailhan nga ang linya gi-lock.

Aw, kompletohon nato ang transaksyon.

=> COMMIT;

Mga indeks

Hangtod karon naghisgut lang kami bahin sa mga panid sa lamesa. Unsa ang mahitabo sa sulod sa mga indeks?

Ang impormasyon sa mga panid sa indeks managlahi kaayo depende sa piho nga matang sa indeks. Ug bisan ang usa ka klase sa indeks adunay lainlain nga klase sa mga panid. Pananglitan, ang usa ka B-tree adunay usa ka metadata nga panid ug "regular" nga mga panid.

Bisan pa, ang panid kasagaran adunay daghang mga pointer sa mga linya ug ang mga linya mismo (sama sa panid sa lamesa). Dugang pa, sa katapusan sa panid adunay luna alang sa espesyal nga datos.

Ang mga laray sa mga indeks mahimo usab nga adunay lainlaing mga istruktura depende sa klase sa indeks. Pananglitan, alang sa usa ka B-tree, ang mga laray nga may kalabutan sa mga panid sa dahon naglangkob sa indexing key value ug usa ka reference (ctid) sa katugbang nga laray sa lamesa. Sa kinatibuk-an, ang indeks mahimong ma-istruktura sa usa ka hingpit nga lahi nga paagi.

Ang labing hinungdanon nga punto mao nga wala’y mga bersyon sa linya sa mga indeks sa bisan unsang klase. Aw, o mahimo natong hunahunaon nga ang matag linya girepresentahan sa eksaktong usa ka bersyon. Sa laing pagkasulti, walay xmin ug xmax nga mga natad sa index row header. Mahimo natong hunahunaon nga ang mga link gikan sa index motultol ngadto sa tanang mga bersyon sa lamesa sa mga laray - aron imong mahibal-an kung unsang bersyon ang makita sa transaksyon pinaagi lamang sa pagtan-aw sa lamesa. (Sama sa kanunay, dili kini ang tibuok nga kamatuoran. Sa pipila ka mga kaso, ang visibility map mahimong ma-optimize ang proseso, apan ato kining tan-awon sa mas detalyado sa ulahi.)

Sa parehas nga oras, sa panid sa indeks makit-an namon ang mga punto sa duha nga mga bersyon, ang karon ug ang daan:

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

Virtual nga mga transaksyon

Sa praktis, ang PostgreSQL naggamit sa mga pag-optimize nga nagtugot niini sa "pagtipig" sa mga numero sa transaksyon.

Kung ang usa ka transaksyon nagbasa lamang sa datos, wala kini epekto sa visibility sa mga bersyon sa linya. Busa, ang proseso sa serbisyo una nga nag-isyu sa usa ka virtual xid sa transaksyon. Ang numero naglangkob sa usa ka proseso ID ug usa ka sunod-sunod nga numero.

Ang pag-isyu niini nga numero wala magkinahanglan og pag-synchronize sa tanan nga mga proseso ug busa paspas kaayo. Masinati nato ang laing rason sa paggamit sa mga virtual nga numero kung maghisgot kita bahin sa pagyelo.

Ang mga virtual nga numero wala gikonsiderar sa bisan unsang paagi sa mga snapshot sa datos.

Sa lain-laing mga punto sa panahon, mahimo nga adunay mga virtual nga mga transaksyon sa sistema nga adunay mga numero nga gigamit na, ug kini normal. Apan ang ingon nga numero dili masulat sa mga panid sa datos, tungod kay sa sunod higayon nga ma-access ang panid mahimo’g mawala ang tanan nga kahulugan.

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

Kung ang usa ka transaksyon magsugod sa pag-usab sa datos, gihatagan kini usa ka tinuud, talagsaon nga numero sa transaksyon.

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

=> COMMIT;

Mga Nested nga Transaksyon

Tipigi ang mga puntos

Gihubit sa SQL save points (savepoint), nga nagtugot kanimo sa pagkansela sa bahin sa usa ka transaksyon nga dili kini hingpit nga makabalda. Apan dili kini angay sa dayagram sa ibabaw, tungod kay ang transaksyon adunay parehas nga kahimtang alang sa tanan nga mga pagbag-o niini, ug sa pisikal nga paagi wala’y datos nga gibalik.

Aron ma-implementar kini nga gamit, ang usa ka transaksyon nga adunay savepoint gibahin sa ubay-ubay nga bulag nested nga mga transaksyon (subtransaction), ang kahimtang niini mahimong madumala nga gilain.

Ang mga nested nga transaksyon adunay kaugalingong numero (mas taas kay sa gidaghanon sa nag-unang transaksyon). Ang kahimtang sa mga nested nga mga transaksyon girekord sa naandan nga paagi sa XACT, apan ang katapusan nga kahimtang nagdepende sa kahimtang sa panguna nga transaksyon: kung kini kanselahon, nan ang tanan nga mga nested nga transaksyon kanselado usab.

Ang impormasyon bahin sa transaction nesting gitipigan sa mga file sa PGDATA/pg_subtrans directory. Ang mga file ma-access pinaagi sa mga buffer sa gipaambit nga memorya sa instance, nga giorganisar sa samang paagi sa XACT buffers.

Ayaw paglibog ang mga nested nga transaksyon sa mga awtonomiya nga transaksyon. Ang mga awtonomous nga transaksyon wala magdepende sa usag usa sa bisan unsang paagi, apan ang mga nested nga transaksyon. Wala’y awtonomiya nga mga transaksyon sa regular nga PostgreSQL, ug, tingali, alang sa labing kaayo: gikinahanglan sila, talagsa ra kaayo, ug ang ilang presensya sa ubang mga DBMS naghagit sa pag-abuso, diin ang tanan nag-antos.

Atong hawanan ang lamesa, magsugod sa usa ka transaksyon ug isulod ang laray:

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

Karon magbutang ta og save point ug magsal-ot og laing linya.

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

Timan-i nga ang txid_current() function nagbalik sa nag-unang numero sa transaksyon, dili ang nested nga numero sa transaksyon.

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

Balikan nato ang save point ug isulod ang ikatulo nga linya.

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

Sa panid padayon namon nga makita ang linya nga gidugang sa gikansela nga nested nga transaksyon.

Among giayo ang mga pagbag-o.

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

Karon klaro nimong makita nga ang matag nested nga transaksyon adunay kaugalingon nga kahimtang.

Timan-i nga ang mga nested nga transaksyon dili mahimong gamiton sa klaro sa SQL, nga mao, dili ka makasugod ug bag-ong transaksyon nga dili makompleto ang kasamtangan. Kini nga mekanismo gi-aktibo sa hingpit kung gigamit ang mga savepoint, ingon man kung nagdumala sa mga eksepsiyon sa PL/pgSQL ug sa daghang uban pa, labi ka lahi nga mga kaso.

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

Mga kasaypanan ug atomicity sa mga operasyon

Unsa ang mahitabo kung adunay usa ka sayup nga nahitabo samtang nagpahigayon sa usa ka operasyon? Pananglitan, sama niini:

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

Usa ka sayup ang nahitabo. Karon ang transaksyon giisip nga gi-abort ug walay mga operasyon nga gitugotan niini:

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

Ug bisan kung gisulayan nimo nga buhaton ang mga pagbag-o, ang PostgreSQL magreport sa usa ka abort:

=> COMMIT;
ROLLBACK

Ngano nga ang usa ka transaksyon dili magpadayon pagkahuman sa pagkapakyas? Ang kamatuoran mao nga ang usa ka kasaypanan mahimong motumaw sa paagi nga kita makakuha og access sa bahin sa mga pagbag-o - ang atomicity bisan sa transaksyon, apan ang operator malapas. Sama sa among pananglitan, diin ang operator nakahimo sa pag-update sa usa ka linya sa wala pa ang sayup:

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

Kinahanglang isulti nga ang psql adunay mode nga nagtugot gihapon sa transaksyon nga magpadayon pagkahuman sa usa ka kapakyasan ingon nga ang mga aksyon sa sayup nga operator gibalik.

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

Dili lisud ang pagtag-an nga sa kini nga mode, ang psql sa tinuud nagbutang usa ka implicit save point sa wala pa ang matag mando, ug kung adunay kapakyasan magsugod sa usa ka rollback niini. Kini nga mode wala gigamit sa default, tungod kay ang pag-set sa mga savepoint (bisan kung wala kini gibalik) nag-apil sa hinungdanon nga overhead.

Pagpadayon.

Source: www.habr.com

Idugang sa usa ka comment