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

Commitefd6cad

Browse files
committed
Tweak heap_update/delete so that we do not hold the buffer context lock
on the old tuple's page while we are doing TOAST pushups.
1 parent0b5d194 commitefd6cad

File tree

2 files changed

+74
-51
lines changed

2 files changed

+74
-51
lines changed

‎src/backend/access/heap/heapam.c

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.107 2001/01/12 21:53:54 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.108 2001/01/15 05:29:19 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1534,18 +1534,20 @@ heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
15341534
}
15351535
END_CRIT_SECTION();
15361536

1537+
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
1538+
15371539
#ifdefTUPLE_TOASTER_ACTIVE
15381540
/* ----------
15391541
* If the relation has toastable attributes, we need to delete
1540-
* no longer needed items there too.
1542+
* no longer needed items there too. We have to do this before
1543+
* WriteBuffer because we need to look at the contents of the tuple,
1544+
* but it's OK to release the context lock on the buffer first.
15411545
* ----------
15421546
*/
15431547
if (HeapTupleHasExtended(&tp))
15441548
heap_tuple_toast_attrs(relation,NULL,&(tp));
15451549
#endif
15461550

1547-
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
1548-
15491551
/*
15501552
* Mark tuple for invalidation from system caches at next command boundary.
15511553
* We have to do this before WriteBuffer because we need to look at the
@@ -1568,7 +1570,10 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
15681570
ItemIdlp;
15691571
HeapTupleDataoldtup;
15701572
PageHeaderdp;
1571-
Bufferbuffer,newbuf;
1573+
Bufferbuffer,
1574+
newbuf;
1575+
boolneed_toast,
1576+
already_marked;
15721577
intresult;
15731578

15741579
/* increment access statistics */
@@ -1645,77 +1650,92 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
16451650
returnresult;
16461651
}
16471652

1648-
/*XXX order problems if not atomic assignment ??? */
1653+
/*Fill in OID and transaction status data for newtup */
16491654
newtup->t_data->t_oid=oldtup.t_data->t_oid;
16501655
TransactionIdStore(GetCurrentTransactionId(),&(newtup->t_data->t_xmin));
16511656
newtup->t_data->t_cmin=GetCurrentCommandId();
16521657
StoreInvalidTransactionId(&(newtup->t_data->t_xmax));
16531658
newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
16541659
newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID |HEAP_UPDATED);
16551660

1656-
#ifdefTUPLE_TOASTER_ACTIVE
1657-
/* ----------
1658-
* If this relation is enabled for toasting, let the toaster
1659-
* delete any no-longer-needed entries and create new ones to
1660-
* make the new tuple fit again. Also, if there are already-
1661-
* toasted values from some other relation, the toaster must
1662-
* fix them.
1663-
* ----------
1661+
/*
1662+
* If the toaster needs to be activated, OR if the new tuple will not
1663+
* fit on the same page as the old, then we need to release the context
1664+
* lock (but not the pin!) on the old tuple's buffer while we are off
1665+
* doing TOAST and/or table-file-extension work. We must mark the old
1666+
* tuple to show that it's already being updated, else other processes
1667+
* may try to update it themselves. To avoid second XLOG log record,
1668+
* we use xact mgr hook to unlock old tuple without reading log if xact
1669+
* will abort before update is logged. In the event of crash prio logging,
1670+
* TQUAL routines will see HEAP_XMAX_UNLOGGED flag...
1671+
*
1672+
* NOTE: this trick is useless currently but saved for future
1673+
* when we'll implement UNDO and will re-use transaction IDs
1674+
* after postmaster startup.
1675+
*
1676+
* We need to invoke the toaster if there are already any toasted values
1677+
* present, or if the new tuple is over-threshold.
16641678
*/
1665-
if (HeapTupleHasExtended(&oldtup)||
1666-
HeapTupleHasExtended(newtup)||
1667-
(MAXALIGN(newtup->t_len)>TOAST_TUPLE_THRESHOLD))
1668-
heap_tuple_toast_attrs(relation,newtup,&oldtup);
1669-
#endif
1679+
need_toast= (HeapTupleHasExtended(&oldtup)||
1680+
HeapTupleHasExtended(newtup)||
1681+
(MAXALIGN(newtup->t_len)>TOAST_TUPLE_THRESHOLD));
16701682

1671-
/* Find buffer for new tuple */
1672-
1673-
if ((unsigned)MAXALIGN(newtup->t_len) <=PageGetFreeSpace((Page)dp))
1674-
newbuf=buffer;
1675-
else
1683+
if (need_toast||
1684+
(unsigned)MAXALIGN(newtup->t_len)>PageGetFreeSpace((Page)dp))
16761685
{
1677-
/*
1678-
* We have to unlock old tuple buffer before extending table
1679-
* file but have to keep lock on the old tuple. To avoid second
1680-
* XLOG log record we use xact mngr hook to unlock old tuple
1681-
* without reading log if xact will abort before update is logged.
1682-
* In the event of crash prio logging, TQUAL routines will see
1683-
* HEAP_XMAX_UNLOGGED flag...
1684-
*
1685-
* NOTE: this trick is useless currently but saved for future
1686-
* when we'll implement UNDO and will re-use transaction IDs
1687-
* after postmaster startup.
1688-
*/
16891686
_locked_tuple_.node=relation->rd_node;
16901687
_locked_tuple_.tid=oldtup.t_self;
16911688
XactPushRollback(_heap_unlock_tuple, (void*)&_locked_tuple_);
16921689

1693-
TransactionIdStore(GetCurrentTransactionId(),&(oldtup.t_data->t_xmax));
1690+
TransactionIdStore(GetCurrentTransactionId(),
1691+
&(oldtup.t_data->t_xmax));
16941692
oldtup.t_data->t_cmax=GetCurrentCommandId();
16951693
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
1696-
HEAP_XMAX_INVALID |HEAP_MARKED_FOR_UPDATE);
1694+
HEAP_XMAX_INVALID |
1695+
HEAP_MARKED_FOR_UPDATE);
16971696
oldtup.t_data->t_infomask |=HEAP_XMAX_UNLOGGED;
1697+
already_marked= true;
16981698
LockBuffer(buffer,BUFFER_LOCK_UNLOCK);
1699-
newbuf=RelationGetBufferForTuple(relation,newtup->t_len);
1699+
1700+
/* Let the toaster do its thing */
1701+
if (need_toast)
1702+
heap_tuple_toast_attrs(relation,newtup,&oldtup);
1703+
1704+
/* Now, do we need a new page for the tuple, or not? */
1705+
if ((unsigned)MAXALIGN(newtup->t_len) <=PageGetFreeSpace((Page)dp))
1706+
newbuf=buffer;
1707+
else
1708+
newbuf=RelationGetBufferForTuple(relation,newtup->t_len);
1709+
1710+
/* Re-acquire the lock on the old tuple's page. */
17001711
/* this seems to be deadlock free... */
17011712
LockBuffer(buffer,BUFFER_LOCK_EXCLUSIVE);
17021713
}
1714+
else
1715+
{
1716+
/* No TOAST work needed, and it'll fit on same page */
1717+
already_marked= false;
1718+
newbuf=buffer;
1719+
}
17031720

17041721
/* NO ELOG(ERROR) from here till changes are logged */
17051722
START_CRIT_SECTION();
17061723

17071724
RelationPutHeapTuple(relation,newbuf,newtup);/* insert new tuple */
1708-
if (buffer==newbuf)
1725+
1726+
if (already_marked)
17091727
{
1710-
TransactionIdStore(GetCurrentTransactionId(),&(oldtup.t_data->t_xmax));
1711-
oldtup.t_data->t_cmax=GetCurrentCommandId();
1712-
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
1713-
HEAP_XMAX_INVALID |HEAP_MARKED_FOR_UPDATE);
1728+
oldtup.t_data->t_infomask &= ~HEAP_XMAX_UNLOGGED;
1729+
XactPopRollback();
17141730
}
17151731
else
17161732
{
1717-
oldtup.t_data->t_infomask &= ~HEAP_XMAX_UNLOGGED;
1718-
XactPopRollback();
1733+
TransactionIdStore(GetCurrentTransactionId(),
1734+
&(oldtup.t_data->t_xmax));
1735+
oldtup.t_data->t_cmax=GetCurrentCommandId();
1736+
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
1737+
HEAP_XMAX_INVALID |
1738+
HEAP_MARKED_FOR_UPDATE);
17191739
}
17201740

17211741
/* record address of new tuple in t_ctid of old one */
@@ -1724,7 +1744,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
17241744
/* XLOG stuff */
17251745
{
17261746
XLogRecPtrrecptr=log_heap_update(relation,buffer,oldtup.t_self,
1727-
newbuf,newtup, false);
1747+
newbuf,newtup, false);
17281748

17291749
if (newbuf!=buffer)
17301750
{
@@ -1734,6 +1754,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
17341754
PageSetLSN(BufferGetPage(buffer),recptr);
17351755
PageSetSUI(BufferGetPage(buffer),ThisStartUpID);
17361756
}
1757+
17371758
END_CRIT_SECTION();
17381759

17391760
if (newbuf!=buffer)

‎src/backend/access/heap/tuptoaster.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.13 2000/10/23 23:42:04 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.14 2001/01/15 05:29:19 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -197,10 +197,12 @@ toast_delete(Relation rel, HeapTuple oldtup)
197197
*/
198198
for (i=0;i<numAttrs;i++)
199199
{
200-
value=heap_getattr(oldtup,i+1,tupleDesc,&isnull);
201-
if (!isnull&&att[i]->attlen==-1)
202-
if (VARATT_IS_EXTERNAL(value))
200+
if (att[i]->attlen==-1)
201+
{
202+
value=heap_getattr(oldtup,i+1,tupleDesc,&isnull);
203+
if (!isnull&&VARATT_IS_EXTERNAL(value))
203204
toast_delete_datum(rel,value);
205+
}
204206
}
205207
}
206208

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp