diff --git a/src/common/backend/utils/cache/knl_localsysdbcache.cpp b/src/common/backend/utils/cache/knl_localsysdbcache.cpp index aa58fdc8a..11dfb0037 100644 --- a/src/common/backend/utils/cache/knl_localsysdbcache.cpp +++ b/src/common/backend/utils/cache/knl_localsysdbcache.cpp @@ -432,7 +432,6 @@ Size *GetSizeVfdCachePtr() } } - int GetVfdNfile() { if (EnableLocalSysCache()) { @@ -524,19 +523,49 @@ bool LocalSysDBCache::LocalSysDBCacheNeedClearMyDB(Oid db_id, const char *db_nam strcmp(t_thrd.proc_cxt.MyProgName, "BootStrap") == 0 )); } + /* it is a weird design that we need access mydatabaseid before initsession. + * but for GSC mode, we do need aquire lock when cache hit and there are invalid msgs + * with session uninited and so u_sess->proc_cxt.MyDatabaseId is InvalidOid. + * 1 the publication feature will send all rels' invalmsgs even no refered ddl. + * 2 relations may have refcount leak, so we must rebuild them if cache hit. + * when we rebuild a relation, the session may be not uninited, + * and so u_sess->proc_cxt.MyDatabaseId is InvalidOid, + * so we use t_thrd.lsc_cxt.lsc->my_database_id on GSC mode */ + Assert(CheckMyDatabaseMatch()); + Assert(m_global_db != NULL); + /* if u_sess->proc_cxt.MyDatabaseId is InvalidOid, the session's status is uninit + * we will call SetDatabase to rewrite it. + * but beofre SetDatabase, we need the dbid to Accept Invalid msg */ + bool lock_db_advance = u_sess->proc_cxt.MyDatabaseId == InvalidOid && IS_THREAD_POOL_WORKER; /* cache hit, when initsession, we lock db to avoid alter db */ - Oid old_db_id = t_thrd.proc->databaseId; - if (u_sess->proc_cxt.MyDatabaseId == InvalidOid && IS_THREAD_POOL_WORKER) { - LockSharedObject(DatabaseRelationId, my_database_id, 0, RowExclusiveLock); + if (lock_db_advance) { + Assert(u_sess->proc_cxt.MyDatabaseTableSpace == InvalidOid); + Assert(u_sess->proc_cxt.DatabasePath == NULL); + Assert(t_thrd.proc->databaseId == InvalidOid); + + u_sess->proc_cxt.MyDatabaseId = my_database_id; + u_sess->proc_cxt.MyDatabaseTableSpace = my_database_tablespace; + /* use refer not copy, it will be rewritten when initsession */ + u_sess->proc_cxt.DatabasePath = my_database_path; + + /* we dont want to accept inval msg here, so use LockSharedObjectForSession to avoid it. */ + LockSharedObjectForSession(DatabaseRelationId, my_database_id, 0, RowExclusiveLock); t_thrd.proc->databaseId = my_database_id; - UnlockSharedObject(DatabaseRelationId, my_database_id, 0, RowExclusiveLock); - } - Assert(m_global_db != NULL); - if (m_global_db->m_isDead) { - t_thrd.proc->databaseId = old_db_id; + UnlockSharedObjectForSession(DatabaseRelationId, my_database_id, 0, RowExclusiveLock); + + /* when we acquired the dblock, alter db transaction happened, and we should clear cache of mydb. */ + if (m_global_db->m_isDead) { + t_thrd.proc->databaseId = InvalidOid; + u_sess->proc_cxt.MyDatabaseId = InvalidOid; + u_sess->proc_cxt.MyDatabaseTableSpace = InvalidOid; + u_sess->proc_cxt.DatabasePath = NULL; + return true; + } + } else if (m_global_db->m_isDead) { return true; } + return false; } diff --git a/src/common/backend/utils/cache/knl_localtabdefcache.cpp b/src/common/backend/utils/cache/knl_localtabdefcache.cpp index 46d3f77e0..704c44bc0 100644 --- a/src/common/backend/utils/cache/knl_localtabdefcache.cpp +++ b/src/common/backend/utils/cache/knl_localtabdefcache.cpp @@ -816,8 +816,9 @@ void LocalTabDefCache::RememberToFreeTupleDescAtEOX(TupleDesc td) { if (EOXactTupleDescArray == NULL) { MemoryContext oldcxt = MemoryContextSwitchTo(LocalMyDBCacheMemCxt()); - EOXactTupleDescArrayLen = 16; - EOXactTupleDescArray = (TupleDesc *)palloc(EOXactTupleDescArrayLen * sizeof(TupleDesc)); + const int default_len = 16; + EOXactTupleDescArray = (TupleDesc *)palloc(default_len * sizeof(TupleDesc)); + EOXactTupleDescArrayLen = default_len; NextEOXactTupleDescNum = 0; MemoryContextSwitchTo(oldcxt); } else if (NextEOXactTupleDescNum >= EOXactTupleDescArrayLen) { diff --git a/src/common/backend/utils/init/postinit.cpp b/src/common/backend/utils/init/postinit.cpp index f448b775a..76a3563dc 100644 --- a/src/common/backend/utils/init/postinit.cpp +++ b/src/common/backend/utils/init/postinit.cpp @@ -66,6 +66,7 @@ #include "storage/ipc.h" #include "storage/smgr/knl_usync.h" #include "storage/lmgr.h" +#include "storage/predicate.h" #include "storage/proc.h" #include "storage/procarray.h" #include "storage/procsignal.h" @@ -2031,7 +2032,6 @@ void PostgresInitializer::InitThread() on_shmem_exit(ShutdownXLOG, 0); } } - void PostgresInitializer::InitLoadLocalSysCache(Oid db_oid, const char *db_name) { if(!EnableLocalSysCache()) { @@ -2068,6 +2068,11 @@ void PostgresInitializer::InitLoadLocalSysCache(Oid db_oid, const char *db_name) ResourceOwnerRelease(t_thrd.lsc_cxt.lsc->local_sysdb_resowner, RESOURCE_RELEASE_LOCKS, false, true); ResourceOwnerRelease(t_thrd.lsc_cxt.lsc->local_sysdb_resowner, RESOURCE_RELEASE_AFTER_LOCKS, false, true); + /* we are not in transaction, so resowner cannot help us release proclocks and predicatelocks. + * we do nothing above except init and load syscache, so no undowork need. ProcReleaseLocks always need + * */ + ProcReleaseLocks(false); + ReleasePredicateLocks(false); /* lwlocks arre released at sigsetjmp */ /* recovery CurrentResourceOwner */ @@ -2590,8 +2595,9 @@ void PostgresInitializer::SetDatabasePath() ValidatePgVersion(m_fullpath); - /* This should happen only once per process */ - Assert(!u_sess->proc_cxt.DatabasePath); + /* This should happen only once per process, for gsc, it may equal the pointer belongs to lsc */ + Assert(!u_sess->proc_cxt.DatabasePath || + (EnableLocalSysCache() && u_sess->proc_cxt.DatabasePath == t_thrd.lsc_cxt.lsc->my_database_path)); u_sess->proc_cxt.DatabasePath = MemoryContextStrdup( SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_EXECUTOR), m_fullpath); if (EnableLocalSysCache()) { diff --git a/src/gausskernel/cbb/instruments/statement/instr_statement.cpp b/src/gausskernel/cbb/instruments/statement/instr_statement.cpp index 89e2d8ab2..2541fcc29 100755 --- a/src/gausskernel/cbb/instruments/statement/instr_statement.cpp +++ b/src/gausskernel/cbb/instruments/statement/instr_statement.cpp @@ -1399,12 +1399,10 @@ void instr_stmt_report_basic_info() } if (to_update_db_name || to_update_user_name || to_update_client_addr) { ResourceOwner old_cur_owner = t_thrd.utils_cxt.CurrentResourceOwner; - MemoryContext old_ctx = MemoryContextSwitchTo(t_thrd.mem_cxt.msg_mem_cxt); - t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(NULL, "Full/Slow SQL", + t_thrd.utils_cxt.CurrentResourceOwner = ResourceOwnerCreate(old_cur_owner, "Full/Slow SQL", THREAD_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_DFX)); - (void)MemoryContextSwitchTo(old_ctx); - old_ctx = MemoryContextSwitchTo(u_sess->statement_cxt.stmt_stat_cxt); + MemoryContext old_ctx = MemoryContextSwitchTo(u_sess->statement_cxt.stmt_stat_cxt); if (to_update_db_name) { u_sess->statement_cxt.db_name = get_database_name(beentry->st_databaseid); }