Satır görünürlüğü tam olarak nasıl belirlenir?


10

En basit durumda, bir tabloya yeni bir satır eklediğimizde (ve işlem gerçekleştiğinde), sonraki tüm işlemler tarafından görülebilir. Bkz xmaxBu örnekte, 0 olan:

CREATE TABLE vis (
  id serial,
  is_active boolean
);

INSERT INTO vis (is_active) VALUES (FALSE);

SELECT ctid, xmin, xmax, * FROM vis;

  ctid xmin  xmax  id  is_active 
───────┼─────┼──────┼────┼───────────
 (0,1) 2699     0   1  f

Güncellediğimizde (bayrak FALSEyanlışlıkla ayarlandığından ), biraz değişir:

UPDATE vis SET is_active = TRUE;

SELECT ctid, xmin, xmax, * FROM vis;

 ctid  xmin  xmax  id  is_active 
──────┼──────┼──────┼────┼───────────
(0,2)  2700     0   1  t

PostgreSQL'in kullandığı MVCC modeline göre , yeni bir fiziksel satır yazıldı ve eskisi geçersiz kılındı ​​(bu, 'den görülebilir ctid). Yeni işlem, sonraki tüm işlemlerde görünmeye devam eder.

Şimdi geri döndüğümüzde ilginç bir şey var UPDATE:

BEGIN;

    UPDATE vis SET is_active = TRUE;

ROLLBACK;

SELECT ctid, xmin, xmax, * FROM vis;

 ctid   xmin  xmax  id  is_active 
───────┼──────┼──────┼────┼───────────
 (0,2)  2700  2702   1  t

Satır sürümü aynı kalır, ancak şimdi bir xmaxşeye ayarlanmıştır. Buna rağmen, sonraki işlemler bu (aksi takdirde değişmemiş) satırı görebilir.

Bu konuda biraz okuduktan sonra, satır görünürlüğü hakkında birkaç şey öğrenebilirsiniz. Orada görünürlük haritası , ancak yalnızca bir bütün sayfa görünür ise söyler - kesinlikle satır (lü) düzeyinde çalışmaz. Sonra kayıt günlüğü var (aka clog) - ama Postgres onu ziyaret etmek zorunda olup olmadığını nasıl anlar?

Görünürlüğün gerçekten nasıl çalıştığını anlamak için bilgi bitlerine bakmaya karar verdim . Bunları görmenin en kolay yolu pageinspect uzantısını kullanmaktır . Hangi bitlerin ayarlandığını bulmak için bunları saklamak için bir tablo oluşturdum:

CREATE TABLE infomask (
  i_flag text,
  i_bits bit(16)
);

INSERT INTO infomask
VALUES 
('HEAP_HASNULL', x'0001'::bit(16)),
('HEAP_HASVARWIDTH', x'0002'::bit(16)),
('HEAP_HASEXTERNAL', x'0004'::bit(16)),
('HEAP_HASOID', x'0008'::bit(16)),
('HEAP_XMAX_KEYSHR_LOCK', x'0010'::bit(16)),
('HEAP_COMBOCID', x'0020'::bit(16)),
('HEAP_XMAX_EXCL_LOCK', x'0040'::bit(16)),
('HEAP_XMAX_LOCK_ONLY', x'0080'::bit(16)),
('HEAP_XMIN_COMMITTED', x'0100'::bit(16)),
('HEAP_XMIN_INVALID', x'0200'::bit(16)),
('HEAP_XMAX_COMMITTED', x'0400'::bit(16)),
('HEAP_XMAX_INVALID', x'0800'::bit(16)),
('HEAP_XMAX_IS_MULTI', x'1000'::bit(16)),
('HEAP_UPDATED', x'2000'::bit(16)),
('HEAP_MOVED_OFF', x'4000'::bit(16)),
('HEAP_MOVED_IN', x'8000'::bit(16)),
('HEAP_XACT_MASK', x'FFF0'::bit(16));

Daha sonra masamın içinde ne olduğunu kontrol visedin - pageinspectyığının fiziksel içeriğini gösteren not , böylece sadece görünür satırlar döndürülmez:

SELECT t_xmin, t_xmax, string_agg(i_flag, ', ') FILTER (WHERE (t_infomask::bit(16) & i_bits)::integer::boolean)
  FROM heap_page_items(get_raw_page('vis', 0)),
       infomask
 GROUP BY t_xmin, t_xmax;

 t_xmin  t_xmax                       string_agg                      
────────┼────────┼──────────────────────────────────────────────────────
   2699    2700  HEAP_XMIN_COMMITTED, HEAP_XMAX_COMMITTED
   2700    2702  HEAP_XMIN_COMMITTED, HEAP_XMAX_INVALID, HEAP_UPDATED
   2702       0  HEAP_XMIN_INVALID, HEAP_XMAX_INVALID, HEAP_UPDATED

Yukarıda anladığım şey, ilk sürümün 2699 işlemiyle hayata geçirilmiş, daha sonra başarıyla 2700'de yeni sürümle değiştirilmiş olmasıdır.
Daha sonra 2700'den beri hayatta olan bir sonraki sürüm 2702'de geri çekilmiş bir girişime sahipti UPDATE. HEAP_XMAX_INVALID.
Sonuncusu asla gösterildiği gibi gerçekten doğmadı HEAP_XMIN_INVALID.

Yani, yukarıdan tahmin etmek, ilk ve son durum açıktır - 2703 veya daha yüksek işlemlerde artık görünmezler.
İkincisi bir yere bakmalı - sanırım bu işlem kayıt günlüğü, aka clog.

Sorunları daha da karmaşıklaştırmak için, daha sonra UPDATEaşağıdakilerle sonuçlanır:

 t_xmin  t_xmax                      string_agg                     
────────┼────────┼────────────────────────────────────────────────────
   2699    2700  HEAP_XMIN_COMMITTED, HEAP_XMAX_COMMITTED
   2702       0  HEAP_XMIN_INVALID, HEAP_XMAX_INVALID, HEAP_UPDATED
   2703       0  HEAP_XMAX_INVALID, HEAP_UPDATED
   2700    2703  HEAP_XMIN_COMMITTED, HEAP_UPDATED

Burada zaten görülebilecek iki aday görüyorum. Son olarak, işte sorularım:

  • clogBu durumlarda görünürlüğü belirlemek için bakılacak yer olduğu varsayımım mı ?
  • Hangi bayraklar (veya bayrak kombinasyonları) sisteme clog?
  • İçinde ne olduğunu incelemenin bir yolu var mı clog? clogPostgres'in önceki sürümlerinde yolsuzluktan bahsediliyor ve sahte bir dosyayı manuel olarak oluşturabileceğinize dair bir ipucu var. Bu bilgi bu konuda çok yardımcı olacaktır.

Yanıtlar:


6

Yani, yukarıdan tahmin etmek, ilk ve son durum açıktır - 2703 veya daha yüksek işlemlerde artık görünmezler. İkincisinin bir yere bakması gerekiyor - sanırım taahhüt günlüğü, yani takunya.

İkincisi var HEAP_XMAX_INVALID. Bu, tıkanıklığa danışmak zorunda olmadığı anlamına gelir, çünkü biri zaten yapmış, xmaxbunun iptal edildiğini gördü ve gelecekteki süreçlerin bu satır için tıkanıklığı tekrar ziyaret etmesine gerek kalmayacak şekilde bir "ipucu biti" ayarladı.

Hangi bayraklar (veya bayrak kombinasyonları) sisteme tıkanıklığı ziyaret etmesini söyler?

Hayır heap_xmin_committedya da yoksa heap_xmin_invalid, xmin düzeninin ne olduğunu görmek için tıkanıklığı ziyaret etmeniz gerekir. İşlem hala devam ediyorsa, satır size görünmez ve hiçbir bayrak ayarlayamazsınız. İşlem tamamlanırsa veya geri alınırsa , heap_xmin_committedya da heap_xmin_invalidbuna göre (bunu yapmak uygunsa - zorunlu değildir) ayarlarsınız, böylece gelecekteki insanların aramasına gerek kalmaz.

Eğer xmingeçerli ve kararlı ise ve xmaxsıfır değildir ve orada hayır heap_max_committedya heap_max_invalido zaman o işlemin eğilim olduğunu görmek için yapışmasına neden ziyaret etmek zorunda.

Tıkanıklığın içinde ne olduğunu incelemenin bir yolu var mı? Postgres'in önceki sürümlerinde tıkanıklık bozulması ve sahte bir dosyayı manuel olarak oluşturabileceğine dair bir ipucu var. Bu bilgi bu konuda çok yardımcı olacaktır.

Bunu yapmanın kullanıcı dostu bir yolunun farkında değilim. Tıkanma dosyalarını incelemek için uygun bir şekilde dökmek için "od" komutunu kullanabilir ve içinde tanımlanan makroları kullanarak nerede denetleyeceğinizi anlayabilirsiniz.src/backend/access/transam/clog.c

PGXN'de sizin için işi yapan herhangi bir uzantı olmadığına şaşırdım, ancak bir tane bulamadım. Ama bence o kadar da kullanışlı olmayacak çünkü sunucunuz çalışmazken bunu yapabilmeniz gerekiyor.


4

HeapTupleSatisfiesMVCC () uygulamasına bir göz atın : Gerçek clogkontrol TransactionIdDidCommit () içinde gerçekleşir , ancak yalnızca işlem durumu bilgi bilgisi bitlerinden ( HeapTupleHeaderXminComended () makro ve arkadaşlar) çıkartılamazsa çağrılır .

Ben pg_clogişlevlerine geri erişim izledim , TransactionDidCommit()ve TransactionDidAbort()sonra bu nerede denir ve sorunuzla ilgili kodunda tek yer içinde görünüyordu baktım HeapTupleSatisfiesMVCC(). Bu işlevin kodundan, gerçek tıkanıklık aramasının yalnızca tuple ilgili infomask bitleri ayarlanmadığında gerçekleşebileceğini görebilirsiniz: kod, HeapTupleHeaderXminCommitted()et al ile bitleri kontrol ederek başlar . Tıkanma araması yalnızca bit (ler) ayarlanmadıysa olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.