Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  inplace.spec   Sprache: unbekannt

 
Spracherkennung für: .spec vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

# Test race conditions involving:
# - s1: VACUUM inplace-updating a pg_class row
# - s2: GRANT/REVOKE making pg_class rows dead
# - s3: "VACUUM pg_class" making dead rows LP_UNUSED; DDL reusing them

# Need GRANT to make a non-HOT update.  Otherwise, "VACUUM pg_class" would
# leave an LP_REDIRECT that persists.  To get non-HOT, make rels so the
# pg_class row for vactest.orig50 is on a filled page (assuming BLCKSZ=8192).
# Just to save on filesystem syscalls, use relkind=c for every other rel.
setup
{
 CREATE EXTENSION injection_points;
 CREATE SCHEMA vactest;
 CREATE FUNCTION vactest.mkrels(text, int, int) RETURNS void
  LANGUAGE plpgsql SET search_path = vactest AS $$
 DECLARE
  tname text;
 BEGIN
  FOR i in $2 .. $3 LOOP
   tname := $1 || i;
   EXECUTE FORMAT('CREATE TYPE ' || tname || ' AS ()');
   RAISE DEBUG '% at %', tname, ctid
    FROM pg_class WHERE oid = tname::regclass;
  END LOOP;
 END
 $$;
}
setup { VACUUM FULL pg_class;  -- reduce free space }
setup
{
 SELECT vactest.mkrels('orig', 149);
 CREATE TABLE vactest.orig50 ();
 SELECT vactest.mkrels('orig', 51100);
}
teardown
{
 DROP SCHEMA vactest CASCADE;
 DROP EXTENSION injection_points;
}

# Wait during inplace update, in a VACUUM of vactest.orig50.
session s1
setup {
 SELECT injection_points_set_local();
 SELECT injection_points_attach('inplace-before-pin', 'wait');
}
step vac1 { VACUUM vactest.orig50;  -- wait during inplace update }
# One bug scenario leaves two live pg_class tuples for vactest.orig50 and zero
# live tuples for one of the "intruder" rels.  REINDEX observes the duplicate.
step read1 {
 REINDEX TABLE pg_class;  -- look for duplicates
 SELECT reltuples = -1 AS reltuples_unknown
 FROM pg_class WHERE oid = 'vactest.orig50'::regclass;
}

# Transactional updates of the tuple vac1 is waiting to inplace-update.
session s2
step grant2  { GRANT SELECT ON TABLE vactest.orig50 TO PUBLIC; }
step revoke2 { REVOKE SELECT ON TABLE vactest.orig50 FROM PUBLIC; }
step begin2  { BEGIN; }
step c2   { COMMIT; }
step r2   { ROLLBACK; }

# Non-blocking actions.
session s3
step vac3  { VACUUM pg_class; }
# Reuse the lp that vac1 is waiting to change.  I've observed reuse at the 1st
# or 18th CREATE, so create excess.
step mkrels3 {
 SELECT vactest.mkrels('intruder', 1100);  -- repopulate LP_UNUSED
 SELECT injection_points_detach('inplace-before-pin');
 SELECT injection_points_wakeup('inplace-before-pin');
}


# target gains a successor at the last moment
permutation
 vac1(mkrels3) # reads pg_class tuple T0 for vactest.orig50, xmax invalid
 grant2   # T0 becomes eligible for pruning, T1 is successor
 vac3   # T0 becomes LP_UNUSED
 mkrels3   # vac1 wakes, scans to T1
 read1

# target already has a successor, which commits
permutation
 begin2
 grant2   # T0.t_ctid = T1
 vac1(mkrels3) # reads T0 for vactest.orig50
 c2    # T0 becomes eligible for pruning
 vac3   # T0 becomes LP_UNUSED
 mkrels3   # vac1 wakes, scans to T1
 read1

# target already has a successor, which becomes LP_UNUSED at the last moment
permutation
 begin2
 grant2   # T0.t_ctid = T1
 vac1(mkrels3) # reads T0 for vactest.orig50
 r2    # T1 becomes eligible for pruning
 vac3   # T1 becomes LP_UNUSED
 mkrels3   # reuse T1; vac1 scans to T0
 read1

# target already has a successor, which becomes LP_REDIRECT at the last moment
permutation
 begin2
 grant2   # T0.t_ctid = T1, non-HOT due to filled page
 vac1(mkrels3) # reads T0
 c2
 revoke2   # HOT update to T2
 grant2   # HOT update to T3
 vac3   # T1 becomes LP_REDIRECT
 mkrels3   # reuse T2; vac1 scans to T3
 read1

# waiting for updater to end
permutation
 vac1(c2)  # reads pg_class tuple T0 for vactest.orig50, xmax invalid
 begin2
 grant2   # T0.t_ctid = T1, non-HOT due to filled page
 revoke2   # HOT update to T2
 mkrels3   # vac1 awakes briefly, then waits for s2
 c2
 read1

# Another LP_UNUSED.  This time, do change the live tuple.  Final live tuple
# body is identical to original, at a different TID.
permutation
 begin2
 grant2   # T0.t_ctid = T1, non-HOT due to filled page
 vac1(mkrels3) # reads T0
 r2    # T1 becomes eligible for pruning
 grant2   # T0.t_ctid = T2; T0 becomes eligible for pruning
 revoke2   # T2.t_ctid = T3; T2 becomes eligible for pruning
 vac3   # T0, T1 & T2 become LP_UNUSED
 mkrels3   # reuse T0, T1 & T2; vac1 scans to T3
 read1

# Another LP_REDIRECT.  Compared to the earlier test, omit the last grant2.
# Hence, final live tuple body is identical to original, at a different TID.
permutation begin2 grant2 vac1(mkrels3) c2 revoke2 vac3 mkrels3 read1

[zur Elbe Produktseite wechseln0.15QuellennavigatorsAnalyse erneut starten2026-08-08]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002