Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb72e5fa

Browse files
committed
Adjust time qual checking code so that we always check TransactionIdIsInProgress
before we check commit/abort status. Formerly this was done in some pathsbut not all, with the result that a transaction might be consideredcommitted for some purposes before it became committed for others.Per example found by Jan Wieck.
1 parent4cd4ed0 commitb72e5fa

File tree

1 file changed

+93
-80
lines changed

1 file changed

+93
-80
lines changed

‎src/backend/utils/time/tqual.c

Lines changed: 93 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,28 @@
1111
* "hint" status bits if we see that the inserting or deleting transaction
1212
* has now committed or aborted.
1313
*
14+
* NOTE: must check TransactionIdIsInProgress (which looks in PGPROC array)
15+
* before TransactionIdDidCommit/TransactionIdDidAbort (which look in
16+
* pg_clog). Otherwise we have a race condition: we might decide that a
17+
* just-committed transaction crashed, because none of the tests succeed.
18+
* xact.c is careful to record commit/abort in pg_clog before it unsets
19+
* MyProc->xid in PGPROC array. That fixes that problem, but it also
20+
* means there is a window where TransactionIdIsInProgress and
21+
* TransactionIdDidCommit will both return true. If we check only
22+
* TransactionIdDidCommit, we could consider a tuple committed when a
23+
* later GetSnapshotData call will still think the originating transaction
24+
* is in progress, which leads to application-level inconsistency. The
25+
* upshot is that we gotta check TransactionIdIsInProgress first in all
26+
* code paths, except for a few cases where we are looking at
27+
* subtransactions of our own main transaction and so there can't be any
28+
* race condition.
29+
*
1430
*
1531
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
1632
* Portions Copyright (c) 1994, Regents of the University of California
1733
*
1834
* IDENTIFICATION
19-
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.87 2005/04/28 21:47:16 tgl Exp $
35+
* $PostgreSQL: pgsql/src/backend/utils/time/tqual.c,v 1.88 2005/05/07 21:22:01 tgl Exp $
2036
*
2137
*-------------------------------------------------------------------------
2238
*/
@@ -147,19 +163,19 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
147163

148164
return false;
149165
}
150-
elseif (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
151-
{
152-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
153-
{
154-
tuple->t_infomask |=HEAP_XMIN_INVALID;
155-
SetBufferCommitInfoNeedsSave(buffer);
156-
}
166+
elseif (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
157167
return false;
168+
elseif (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
169+
{
170+
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
171+
SetBufferCommitInfoNeedsSave(buffer);
158172
}
159173
else
160174
{
161-
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
175+
/* it must have aborted or crashed */
176+
tuple->t_infomask |=HEAP_XMIN_INVALID;
162177
SetBufferCommitInfoNeedsSave(buffer);
178+
return false;
163179
}
164180
}
165181

@@ -189,13 +205,14 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple, Buffer buffer)
189205
return false;
190206
}
191207

208+
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
209+
return true;
210+
192211
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
193212
{
194-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
195-
{
196-
tuple->t_infomask |=HEAP_XMAX_INVALID;
197-
SetBufferCommitInfoNeedsSave(buffer);
198-
}
213+
/* it must have aborted or crashed */
214+
tuple->t_infomask |=HEAP_XMAX_INVALID;
215+
SetBufferCommitInfoNeedsSave(buffer);
199216
return true;
200217
}
201218

@@ -330,19 +347,19 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
330347
else
331348
return false;/* deleted before scan started */
332349
}
333-
elseif (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
334-
{
335-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
336-
{
337-
tuple->t_infomask |=HEAP_XMIN_INVALID;
338-
SetBufferCommitInfoNeedsSave(buffer);
339-
}
350+
elseif (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
340351
return false;
352+
elseif (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
353+
{
354+
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
355+
SetBufferCommitInfoNeedsSave(buffer);
341356
}
342357
else
343358
{
344-
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
359+
/* it must have aborted or crashed */
360+
tuple->t_infomask |=HEAP_XMIN_INVALID;
345361
SetBufferCommitInfoNeedsSave(buffer);
362+
return false;
346363
}
347364
}
348365

@@ -375,13 +392,14 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple, Buffer buffer)
375392
return false;/* deleted before scan started */
376393
}
377394

395+
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
396+
return true;
397+
378398
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
379399
{
380-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
381-
{
382-
tuple->t_infomask |=HEAP_XMAX_INVALID;
383-
SetBufferCommitInfoNeedsSave(buffer);
384-
}
400+
/* it must have aborted or crashed */
401+
tuple->t_infomask |=HEAP_XMAX_INVALID;
402+
SetBufferCommitInfoNeedsSave(buffer);
385403
return true;
386404
}
387405

@@ -569,19 +587,19 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
569587
returnHeapTupleInvisible;/* updated before scan
570588
* started */
571589
}
572-
elseif (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
573-
{
574-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
575-
{
576-
tuple->t_infomask |=HEAP_XMIN_INVALID;
577-
SetBufferCommitInfoNeedsSave(buffer);
578-
}
590+
elseif (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
579591
returnHeapTupleInvisible;
592+
elseif (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
593+
{
594+
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
595+
SetBufferCommitInfoNeedsSave(buffer);
580596
}
581597
else
582598
{
583-
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
599+
/* it must have aborted or crashed */
600+
tuple->t_infomask |=HEAP_XMIN_INVALID;
584601
SetBufferCommitInfoNeedsSave(buffer);
602+
returnHeapTupleInvisible;
585603
}
586604
}
587605

@@ -620,16 +638,15 @@ HeapTupleSatisfiesUpdate(HeapTupleHeader tuple, CommandId curcid,
620638
returnHeapTupleInvisible;/* updated before scan started */
621639
}
622640

641+
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
642+
returnHeapTupleBeingUpdated;
643+
623644
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
624645
{
625-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
626-
{
627-
tuple->t_infomask |=HEAP_XMAX_INVALID;
628-
SetBufferCommitInfoNeedsSave(buffer);
629-
returnHeapTupleMayBeUpdated;
630-
}
631-
/* running xact */
632-
returnHeapTupleBeingUpdated;/* in updation by other */
646+
/* it must have aborted or crashed */
647+
tuple->t_infomask |=HEAP_XMAX_INVALID;
648+
SetBufferCommitInfoNeedsSave(buffer);
649+
returnHeapTupleMayBeUpdated;
633650
}
634651

635652
/* xmax transaction committed */
@@ -735,23 +752,24 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
735752

736753
return false;
737754
}
738-
elseif (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
755+
elseif (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
739756
{
740-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
741-
{
742-
tuple->t_infomask |=HEAP_XMIN_INVALID;
743-
SetBufferCommitInfoNeedsSave(buffer);
744-
return false;
745-
}
746757
SnapshotDirty->xmin=HeapTupleHeaderGetXmin(tuple);
747758
/* XXX shouldn't we fall through to look at xmax? */
748759
return true;/* in insertion by other */
749760
}
750-
else
761+
elseif (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
751762
{
752763
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
753764
SetBufferCommitInfoNeedsSave(buffer);
754765
}
766+
else
767+
{
768+
/* it must have aborted or crashed */
769+
tuple->t_infomask |=HEAP_XMIN_INVALID;
770+
SetBufferCommitInfoNeedsSave(buffer);
771+
return false;
772+
}
755773
}
756774

757775
/* by here, the inserting transaction has committed */
@@ -781,17 +799,18 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple, Buffer buffer)
781799
return false;
782800
}
783801

784-
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
802+
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
785803
{
786-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
787-
{
788-
tuple->t_infomask |=HEAP_XMAX_INVALID;
789-
SetBufferCommitInfoNeedsSave(buffer);
790-
return true;
791-
}
792-
/* running xact */
793804
SnapshotDirty->xmax=HeapTupleHeaderGetXmax(tuple);
794-
return true;/* in updation by other */
805+
return true;
806+
}
807+
808+
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
809+
{
810+
/* it must have aborted or crashed */
811+
tuple->t_infomask |=HEAP_XMAX_INVALID;
812+
SetBufferCommitInfoNeedsSave(buffer);
813+
return true;
795814
}
796815

797816
/* xmax transaction committed */
@@ -907,19 +926,19 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot,
907926
else
908927
return false;/* deleted before scan started */
909928
}
910-
elseif (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
911-
{
912-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
913-
{
914-
tuple->t_infomask |=HEAP_XMIN_INVALID;
915-
SetBufferCommitInfoNeedsSave(buffer);
916-
}
929+
elseif (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
917930
return false;
931+
elseif (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
932+
{
933+
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
934+
SetBufferCommitInfoNeedsSave(buffer);
918935
}
919936
else
920937
{
921-
tuple->t_infomask |=HEAP_XMIN_COMMITTED;
938+
/* it must have aborted or crashed */
939+
tuple->t_infomask |=HEAP_XMIN_INVALID;
922940
SetBufferCommitInfoNeedsSave(buffer);
941+
return false;
923942
}
924943
}
925944

@@ -982,13 +1001,14 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot,
9821001
return false;/* deleted before scan started */
9831002
}
9841003

1004+
if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
1005+
return true;
1006+
9851007
if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
9861008
{
987-
if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
988-
{
989-
tuple->t_infomask |=HEAP_XMAX_INVALID;
990-
SetBufferCommitInfoNeedsSave(buffer);
991-
}
1009+
/* it must have aborted or crashed */
1010+
tuple->t_infomask |=HEAP_XMAX_INVALID;
1011+
SetBufferCommitInfoNeedsSave(buffer);
9921012
return true;
9931013
}
9941014

@@ -1057,13 +1077,6 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
10571077
*
10581078
* If the inserting transaction aborted, then the tuple was never visible
10591079
* to any other transaction, so we can delete it immediately.
1060-
*
1061-
* NOTE: must check TransactionIdIsInProgress (which looks in PROC array)
1062-
* before TransactionIdDidCommit/TransactionIdDidAbort (which look in
1063-
* pg_clog). Otherwise we have a race condition where we might decide
1064-
* that a just-committed transaction crashed, because none of the
1065-
* tests succeed. xact.c is careful to record commit/abort in pg_clog
1066-
* before it unsets MyProc->xid in PROC array.
10671080
*/
10681081
if (!(tuple->t_infomask&HEAP_XMIN_COMMITTED))
10691082
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp