Jak porównać xmin i txid_current () po zawinięciu identyfikatora transakcji?

12

Oprócz zwykłych kolumn w tabelach Postgres dostępne są również różne kolumny systemowe . Jeden z nich xminprzechowuje identyfikator transakcji użyty do utworzenia wiersza. Jego typ danych to xidczterobajtowa liczba całkowita, która w pewnym momencie się zawija (tzn. Niekoniecznie jest unikalna). Ta funkcja txid_current()z kolei zwraca bieżący identyfikator transakcji, ale ponieważ bigint, ponieważ „jest on rozszerzony o licznik„ epoki ”, więc nie zawinie się podczas instalacji” (cytując instrukcję ).

Jeśli obejście transakcji jeszcze się nie wydarzyło, obie wartości wydają się pasować:

# CREATE TABLE test (label text);
CREATE TABLE
# INSERT INTO test VALUES ('test') RETURNING txid_current();
 txid_current 
--------------
   674500
(1 row)
INSERT 0 1
# SELECT xmin FROM test;
  xmin  
--------
 674500
(1 row)

Ale zastanawiam się: czy te dwie wartości są zawsze porównywalne? O ile rozumiem, txid_current()nadal będzie dostarczał unikalne wartości po zawinięciu identyfikatora transakcji (maksymalnie 2 ^ 32 transakcje) i xminzacznie od zera. Oznacza to, że oba zaczynają zwracać różne wartości w tym momencie?

I czy to prawda, czy jest jakiś sposób, aby wyodrębnić regularny xidz txid_current()wyniku, tak by pasować xminwpisy w tabeli (np odlewniczej txid_current()do liczby całkowitej)?

Edycja : Wyjaśnij, że zależy mi na tym, co stanie się po zawinięciu identyfikatora transakcji, co najprawdopodobniej nastąpi na długo przed 2 ^ 32 transakcjami. Dzięki Danielowi Vérité za odnotowanie tego w komentarzach.

tomka
źródło
1
Ignorujesz fakt, że system VACUUM FREEZEnadpisze xminwiersze w wierszu na długo przed zawinięciem 2 ^ 32. Sprawdź Freezing Your Tuples Off, aby zapoznać się z omówieniem tego tematu.
Daniel Vérité,
To prawda, że ​​pominąłem ten fakt, dziękuję za wskazanie. I rzeczywiście, zamrożenie nastąpi na długo przed 2 ^ 32. Jednak nawet po xminzamrożeniu starego pytania wciąż pozostaje pytanie, jak nowszy (zwykły) w xminporównaniu z wykonanym wówczas txid_current().
tomka
1
Warto zauważyć, że PostgreSQL zostanie zamknięty, jeśli do momentu zakończenia pozostanie mniej niż 1 milion transakcji .
user103153,

Odpowiedzi:

6

Możesz usunąć dodaną epokę, aby dopasować ją do wartości xmin, tj. Wyodrębnić 4 bajty integerz bigint. Ponieważ xminjest typem, xida nie (podpisanym!) integer, textZamiast tego porównujemy reprezentację:

SELECT * FROM test
WHERE  xmin::text = (txid_current() % (2^32)::bigint)::text;

Szczegółowe wyjaśnienie:

Erwin Brandstetter
źródło