Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1f92630

Browse files
Jan WieckJan Wieck
Jan Wieck
authored and
Jan Wieck
committed
Added the Skytools extended transaction ID module to contrib as discussed
on CORE previously. This module offers transaction ID's containing the original XID and the transaction epoch as a bigint value to the user level. It also provides a special txid_snapshot data type that contains an entire transactions visibility snapshot information, which is useful to determine if a particular txid was visible to a transaction or not. The module has been tested by porting Slony-I from using its original xxid data type. Jan
1 parent 2a997a7 commit 1f92630

File tree

8 files changed

+967
-1
lines changed

8 files changed

+967
-1
lines changed

contrib/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $PostgreSQL: pgsql/contrib/Makefile,v 1.78 2007/08/21 01:12:28 tgl Exp $
1+
# $PostgreSQL: pgsql/contrib/Makefile,v 1.79 2007/10/07 23:32:19 wieck Exp $
22

33
subdir = contrib
44
top_builddir = ..
@@ -30,6 +30,7 @@ WANTED_DIRS = \
3030
pgstattuple \
3131
seg \
3232
spi \
33+
txid \
3334
tablefunc \
3435
vacuumlo
3536

contrib/txid/Makefile

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
MODULES = txid
3+
DATA_built = txid.sql
4+
DATA = uninstall_txid.sql
5+
DOCS = README.txid
6+
REGRESS = txid
7+
8+
9+
ifdef USE_PGXS
10+
PG_CONFIG = pg_config
11+
PGXS := $(shell $(PG_CONFIG) --pgxs)
12+
include $(PGXS)
13+
else
14+
subdir = contrib/txid
15+
top_builddir = ../..
16+
include $(top_builddir)/src/Makefile.global
17+
include $(top_srcdir)/contrib/contrib-global.mk
18+
endif
19+
20+
21+
test: install
22+
$(MAKE) installcheck || { less regression.diffs; exit 1; }
23+
24+
ack:
25+
cp results/* expected/
26+

contrib/txid/README.txid

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
2+
txid - export transaction id's to user level
3+
============================================
4+
5+
The goal is to make PostgreSQL internal transaction ID and snapshot
6+
data usable externally. This allows very efficient queue
7+
implementation done inside database.
8+
9+
[towrite: what snapshot means]
10+
11+
The module defines type txid_snapshot and following functions:
12+
13+
14+
txid_current() returns int8
15+
16+
Current transaction ID.
17+
18+
txid_current_snapshot() returns txid_snapshot
19+
20+
Current snapshot.
21+
22+
txid_snapshot_xmin( snap ) returns int8
23+
24+
Smallest TXID in snapshot. TXID's smaller than this
25+
are all visible in snapshot.
26+
27+
txid_snapshot_xmax( snap ) returns int8
28+
29+
Largest TXID in snapshot. TXID's starting from this one are
30+
all invisible in snapshot.
31+
32+
txid_snapshot_xip( snap ) setof int8
33+
34+
List of in-progress TXID's in snapshot, that are invisible.
35+
Values are between xmin and xmax.
36+
37+
txid_visible_in_snapshot(id, snap) returns bool
38+
39+
Is TXID visible in snapshot?
40+
41+
42+
Fetching events
43+
---------------
44+
45+
Lets say there is following event table:
46+
47+
CREATE TABLE events (
48+
ev_txid int8 not null default txid_current(),
49+
ev_data text
50+
);
51+
CREATE INDEX ev_txid_idx ON events (ev_txid);
52+
53+
Then event between 2 snapshots snap1 and snap2 can be fetched
54+
with followign query:
55+
56+
SELECT ev_data FROM events
57+
WHERE ev_txid >= txid_snapshot_xmin(:snap1)
58+
AND ev_txid < txid_snapshot_xmax(:snap2)
59+
AND NOT txid_visible_in_snapshot(ev_txid, :snap1)
60+
AND txid_visible_in_snapshot(ev_txid, :snap2);
61+
62+
This is the simplest query but it has problem if there are long
63+
transactions running - the txid_snapshot_xmin(snap1) will stay low
64+
and the range will get very large.
65+
66+
This can be fixed by fetching only snap1.xmax ... snap1.xmax by range and
67+
fetching possible txids below snap1.xmax explicitly:
68+
69+
SELECT ev_data FROM events
70+
WHERE ((ev_txid >= txid_snapshot_xmax(:snap1) AND ev_txid < txid_snapshot_xmax(:snap2))
71+
OR
72+
(ev_txid IN (SELECT * FROM txid_snapshot_xip(:snap1))))
73+
AND NOT txid_visible_in_snapshot(ev_txid, :snap1)
74+
AND txid_visible_in_snapshot(ev_txid, :snap2);
75+
76+
Note that although the above queries work, the PostgreSQL fails to
77+
plan them correctly. For actual usage the values for txid_snapshot_xmin,
78+
txid_snapshot_xmax and txid_snapshot_xip should be filled in directly,
79+
only then will they use index.
80+
81+
There are few more optimizations possible, like:
82+
83+
- Picking out only TXIDs that were actually committed between snap1 and snap2.
84+
85+
- Lowering the range from txid_snapshot_xmax(snap1) to decrease the list if TXIDs to be fetched separately.
86+
87+
To see example code for that it's best to see pgq.batch_event_sql() function in Skytools.
88+
89+
http://pgfoundry.org/projects/skytools/
90+
91+
92+
Dumping and restoring data containing TXIDs.
93+
--------------------------------------------
94+
95+
[towrite: reason for epoch increase]
96+
97+
You can look at current epoch with query:
98+
99+
SELECT txid_current() >> 32 as epoch;
100+
101+
So new epoch should be:
102+
103+
SELECT (txid_current() >> 32) + 1 as newepoch;
104+
105+
Epoch can be changed with pg_resetxlog command:
106+
107+
pg_resetxlog -e NEWEPOCH DATADIR
108+
109+
Database needs to be shut down for that moment.
110+
111+

contrib/txid/expected/txid.out

+212
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
-- init
2+
\set ECHO none
3+
-- i/o
4+
select '12:13:'::txid_snapshot;
5+
txid_snapshot
6+
---------------
7+
12:13:
8+
(1 row)
9+
10+
select '12:13:1,2'::txid_snapshot;
11+
ERROR: illegal txid_snapshot input format
12+
-- errors
13+
select '31:12:'::txid_snapshot;
14+
ERROR: illegal txid_snapshot input format
15+
select '0:1:'::txid_snapshot;
16+
ERROR: illegal txid_snapshot input format
17+
select '12:13:0'::txid_snapshot;
18+
ERROR: illegal txid_snapshot input format
19+
select '12:16:14,13'::txid_snapshot;
20+
ERROR: illegal txid_snapshot input format
21+
select '12:16:14,14'::txid_snapshot;
22+
ERROR: illegal txid_snapshot input format
23+
create table snapshot_test (
24+
nr integer,
25+
snap txid_snapshot
26+
);
27+
insert into snapshot_test values (1, '12:13:');
28+
insert into snapshot_test values (2, '12:20:13,15,18');
29+
insert into snapshot_test values (3, '100001:100009:100005,100007,100008');
30+
insert into snapshot_test values (4, '100:150:101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131');
31+
select snap from snapshot_test order by nr;
32+
snap
33+
-------------------------------------------------------------------------------------------------------------------------------------
34+
12:13:
35+
12:20:13,15,18
36+
100001:100009:100005,100007,100008
37+
100:150:101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131
38+
(4 rows)
39+
40+
select txid_snapshot_xmin(snap),
41+
txid_snapshot_xmax(snap),
42+
txid_snapshot_xip(snap)
43+
from snapshot_test order by nr;
44+
txid_snapshot_xmin | txid_snapshot_xmax | txid_snapshot_xip
45+
--------------------+--------------------+-------------------
46+
12 | 20 | 13
47+
12 | 20 | 15
48+
12 | 20 | 18
49+
100001 | 100009 | 100005
50+
100001 | 100009 | 100007
51+
100001 | 100009 | 100008
52+
100 | 150 | 101
53+
100 | 150 | 102
54+
100 | 150 | 103
55+
100 | 150 | 104
56+
100 | 150 | 105
57+
100 | 150 | 106
58+
100 | 150 | 107
59+
100 | 150 | 108
60+
100 | 150 | 109
61+
100 | 150 | 110
62+
100 | 150 | 111
63+
100 | 150 | 112
64+
100 | 150 | 113
65+
100 | 150 | 114
66+
100 | 150 | 115
67+
100 | 150 | 116
68+
100 | 150 | 117
69+
100 | 150 | 118
70+
100 | 150 | 119
71+
100 | 150 | 120
72+
100 | 150 | 121
73+
100 | 150 | 122
74+
100 | 150 | 123
75+
100 | 150 | 124
76+
100 | 150 | 125
77+
100 | 150 | 126
78+
100 | 150 | 127
79+
100 | 150 | 128
80+
100 | 150 | 129
81+
100 | 150 | 130
82+
100 | 150 | 131
83+
(37 rows)
84+
85+
select id, txid_visible_in_snapshot(id, snap)
86+
from snapshot_test, generate_series(11, 21) id
87+
where nr = 2;
88+
id | txid_visible_in_snapshot
89+
----+--------------------------
90+
11 | t
91+
12 | t
92+
13 | f
93+
14 | t
94+
15 | f
95+
16 | t
96+
17 | t
97+
18 | f
98+
19 | t
99+
20 | f
100+
21 | f
101+
(11 rows)
102+
103+
-- test bsearch
104+
select id, txid_visible_in_snapshot(id, snap)
105+
from snapshot_test, generate_series(90, 160) id
106+
where nr = 4;
107+
id | txid_visible_in_snapshot
108+
-----+--------------------------
109+
90 | t
110+
91 | t
111+
92 | t
112+
93 | t
113+
94 | t
114+
95 | t
115+
96 | t
116+
97 | t
117+
98 | t
118+
99 | t
119+
100 | t
120+
101 | f
121+
102 | f
122+
103 | f
123+
104 | f
124+
105 | f
125+
106 | f
126+
107 | f
127+
108 | f
128+
109 | f
129+
110 | f
130+
111 | f
131+
112 | f
132+
113 | f
133+
114 | f
134+
115 | f
135+
116 | f
136+
117 | f
137+
118 | f
138+
119 | f
139+
120 | f
140+
121 | f
141+
122 | f
142+
123 | f
143+
124 | f
144+
125 | f
145+
126 | f
146+
127 | f
147+
128 | f
148+
129 | f
149+
130 | f
150+
131 | f
151+
132 | t
152+
133 | t
153+
134 | t
154+
135 | t
155+
136 | t
156+
137 | t
157+
138 | t
158+
139 | t
159+
140 | t
160+
141 | t
161+
142 | t
162+
143 | t
163+
144 | t
164+
145 | t
165+
146 | t
166+
147 | t
167+
148 | t
168+
149 | t
169+
150 | f
170+
151 | f
171+
152 | f
172+
153 | f
173+
154 | f
174+
155 | f
175+
156 | f
176+
157 | f
177+
158 | f
178+
159 | f
179+
160 | f
180+
(71 rows)
181+
182+
-- test current values also
183+
select txid_current() >= txid_snapshot_xmin(txid_current_snapshot());
184+
?column?
185+
----------
186+
t
187+
(1 row)
188+
189+
/* due to lazy xid alloc in 8.3 those are different in 8.2 and 8.3
190+
select txid_current() < txid_snapshot_xmax(txid_current_snapshot());
191+
192+
select txid_visible_in_snapshot(txid_current(), txid_current_snapshot());
193+
*/
194+
-- test 64bitness
195+
select txid_snapshot '1000100010001000:1000100010001100:1000100010001012,1000100010001013';
196+
txid_snapshot
197+
---------------------------------------------------------------------
198+
1000100010001000:1000100010001100:1000100010001012,1000100010001013
199+
(1 row)
200+
201+
select txid_visible_in_snapshot('1000100010001012', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
202+
txid_visible_in_snapshot
203+
--------------------------
204+
f
205+
(1 row)
206+
207+
select txid_visible_in_snapshot('1000100010001015', '1000100010001000:1000100010001100:1000100010001012,1000100010001013');
208+
txid_visible_in_snapshot
209+
--------------------------
210+
t
211+
(1 row)
212+

0 commit comments

Comments
 (0)