mirror of
https://github.com/postgres/postgres.git
synced 2025-06-23 14:01:44 +03:00
Improve the plan cache invalidation mechanism to make it invalidate plans
when user-defined functions used in a plan are modified. Also invalidate plans when schemas, operators, or operator classes are modified; but for these cases we just invalidate everything rather than tracking exact dependencies, since these types of objects seldom change in a production database. Tom Lane; loosely based on a patch by Martin Pihlak.
This commit is contained in:
84
src/backend/utils/cache/inval.c
vendored
84
src/backend/utils/cache/inval.c
vendored
@ -80,7 +80,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.86 2008/06/19 21:32:56 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.87 2008/09/09 18:58:08 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -160,16 +160,25 @@ static TransInvalidationInfo *transInvalInfo = NULL;
|
||||
* assumes there won't be very many of these at once; could improve if needed.
|
||||
*/
|
||||
|
||||
#define MAX_CACHE_CALLBACKS 20
|
||||
#define MAX_SYSCACHE_CALLBACKS 20
|
||||
#define MAX_RELCACHE_CALLBACKS 5
|
||||
|
||||
static struct CACHECALLBACK
|
||||
static struct SYSCACHECALLBACK
|
||||
{
|
||||
int16 id; /* cache number or message type id */
|
||||
CacheCallbackFunction function;
|
||||
int16 id; /* cache number */
|
||||
SyscacheCallbackFunction function;
|
||||
Datum arg;
|
||||
} cache_callback_list[MAX_CACHE_CALLBACKS];
|
||||
} syscache_callback_list[MAX_SYSCACHE_CALLBACKS];
|
||||
|
||||
static int cache_callback_count = 0;
|
||||
static int syscache_callback_count = 0;
|
||||
|
||||
static struct RELCACHECALLBACK
|
||||
{
|
||||
RelcacheCallbackFunction function;
|
||||
Datum arg;
|
||||
} relcache_callback_list[MAX_RELCACHE_CALLBACKS];
|
||||
|
||||
static int relcache_callback_count = 0;
|
||||
|
||||
/* info values for 2PC callback */
|
||||
#define TWOPHASE_INFO_MSG 0 /* SharedInvalidationMessage */
|
||||
@ -484,12 +493,13 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
|
||||
msg->cc.hashValue,
|
||||
&msg->cc.tuplePtr);
|
||||
|
||||
for (i = 0; i < cache_callback_count; i++)
|
||||
for (i = 0; i < syscache_callback_count; i++)
|
||||
{
|
||||
struct CACHECALLBACK *ccitem = cache_callback_list + i;
|
||||
struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
|
||||
|
||||
if (ccitem->id == msg->cc.id)
|
||||
(*ccitem->function) (ccitem->arg, InvalidOid);
|
||||
(*ccitem->function) (ccitem->arg,
|
||||
msg->cc.id, &msg->cc.tuplePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,12 +509,11 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
|
||||
{
|
||||
RelationCacheInvalidateEntry(msg->rc.relId);
|
||||
|
||||
for (i = 0; i < cache_callback_count; i++)
|
||||
for (i = 0; i < relcache_callback_count; i++)
|
||||
{
|
||||
struct CACHECALLBACK *ccitem = cache_callback_list + i;
|
||||
struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
|
||||
|
||||
if (ccitem->id == SHAREDINVALRELCACHE_ID)
|
||||
(*ccitem->function) (ccitem->arg, msg->rc.relId);
|
||||
(*ccitem->function) (ccitem->arg, msg->rc.relId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -539,9 +548,16 @@ InvalidateSystemCaches(void)
|
||||
ResetCatalogCaches();
|
||||
RelationCacheInvalidate(); /* gets smgr cache too */
|
||||
|
||||
for (i = 0; i < cache_callback_count; i++)
|
||||
for (i = 0; i < syscache_callback_count; i++)
|
||||
{
|
||||
struct CACHECALLBACK *ccitem = cache_callback_list + i;
|
||||
struct SYSCACHECALLBACK *ccitem = syscache_callback_list + i;
|
||||
|
||||
(*ccitem->function) (ccitem->arg, ccitem->id, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < relcache_callback_count; i++)
|
||||
{
|
||||
struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
|
||||
|
||||
(*ccitem->function) (ccitem->arg, InvalidOid);
|
||||
}
|
||||
@ -1177,26 +1193,25 @@ CacheInvalidateRelcacheByRelid(Oid relid)
|
||||
/*
|
||||
* CacheRegisterSyscacheCallback
|
||||
* Register the specified function to be called for all future
|
||||
* invalidation events in the specified cache.
|
||||
* invalidation events in the specified cache. The cache ID and the
|
||||
* TID of the tuple being invalidated will be passed to the function.
|
||||
*
|
||||
* NOTE: currently, the OID argument to the callback routine is not
|
||||
* provided for syscache callbacks; the routine doesn't really get any
|
||||
* useful info as to exactly what changed. It should treat every call
|
||||
* as a "cache flush" request.
|
||||
* NOTE: NULL will be passed for the TID if a cache reset request is received.
|
||||
* In this case the called routines should flush all cached state.
|
||||
*/
|
||||
void
|
||||
CacheRegisterSyscacheCallback(int cacheid,
|
||||
CacheCallbackFunction func,
|
||||
SyscacheCallbackFunction func,
|
||||
Datum arg)
|
||||
{
|
||||
if (cache_callback_count >= MAX_CACHE_CALLBACKS)
|
||||
elog(FATAL, "out of cache_callback_list slots");
|
||||
if (syscache_callback_count >= MAX_SYSCACHE_CALLBACKS)
|
||||
elog(FATAL, "out of syscache_callback_list slots");
|
||||
|
||||
cache_callback_list[cache_callback_count].id = cacheid;
|
||||
cache_callback_list[cache_callback_count].function = func;
|
||||
cache_callback_list[cache_callback_count].arg = arg;
|
||||
syscache_callback_list[syscache_callback_count].id = cacheid;
|
||||
syscache_callback_list[syscache_callback_count].function = func;
|
||||
syscache_callback_list[syscache_callback_count].arg = arg;
|
||||
|
||||
++cache_callback_count;
|
||||
++syscache_callback_count;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1209,15 +1224,14 @@ CacheRegisterSyscacheCallback(int cacheid,
|
||||
* In this case the called routines should flush all cached state.
|
||||
*/
|
||||
void
|
||||
CacheRegisterRelcacheCallback(CacheCallbackFunction func,
|
||||
CacheRegisterRelcacheCallback(RelcacheCallbackFunction func,
|
||||
Datum arg)
|
||||
{
|
||||
if (cache_callback_count >= MAX_CACHE_CALLBACKS)
|
||||
elog(FATAL, "out of cache_callback_list slots");
|
||||
if (relcache_callback_count >= MAX_RELCACHE_CALLBACKS)
|
||||
elog(FATAL, "out of relcache_callback_list slots");
|
||||
|
||||
cache_callback_list[cache_callback_count].id = SHAREDINVALRELCACHE_ID;
|
||||
cache_callback_list[cache_callback_count].function = func;
|
||||
cache_callback_list[cache_callback_count].arg = arg;
|
||||
relcache_callback_list[relcache_callback_count].function = func;
|
||||
relcache_callback_list[relcache_callback_count].arg = arg;
|
||||
|
||||
++cache_callback_count;
|
||||
++relcache_callback_count;
|
||||
}
|
||||
|
Reference in New Issue
Block a user