diff --git a/deps/oblib/src/lib/statistic_event/ob_stat_event.h b/deps/oblib/src/lib/statistic_event/ob_stat_event.h index d71e5db04..a179ba6cd 100644 --- a/deps/oblib/src/lib/statistic_event/ob_stat_event.h +++ b/deps/oblib/src/lib/statistic_event/ob_stat_event.h @@ -204,6 +204,9 @@ STAT_EVENT_ADD_DEF(STORAGE_META_CACHE_MISS, "storage meta cache miss", ObStatCla STAT_EVENT_ADD_DEF(TABLET_CACHE_HIT, "tablet cache hit", ObStatClassIds::CACHE, "tablet cache hit", 50059, true, true) STAT_EVENT_ADD_DEF(TABLET_CACHE_MISS, "tablet cache miss", ObStatClassIds::CACHE, "tablet cache miss", 50060, true, true) +STAT_EVENT_ADD_DEF(SCHEMA_HISTORY_CACHE_HIT, "schema history cache hit", ObStatClassIds::CACHE, "schema cache history hit", 50061, false, true) +STAT_EVENT_ADD_DEF(SCHEMA_HISTORY_CACHE_MISS, "schema history cache miss", ObStatClassIds::CACHE, "schema cache history miss", 50062, false, true) + // STORAGE //STAT_EVENT_ADD_DEF(MEMSTORE_LOGICAL_READS, "MEMSTORE_LOGICAL_READS", STORAGE, "MEMSTORE_LOGICAL_READS") //STAT_EVENT_ADD_DEF(MEMSTORE_LOGICAL_BYTES, "MEMSTORE_LOGICAL_BYTES", STORAGE, "MEMSTORE_LOGICAL_BYTES") diff --git a/src/observer/virtual_table/ob_information_kvcache_table.cpp b/src/observer/virtual_table/ob_information_kvcache_table.cpp index df9fa0a29..dbfba3a0a 100644 --- a/src/observer/virtual_table/ob_information_kvcache_table.cpp +++ b/src/observer/virtual_table/ob_information_kvcache_table.cpp @@ -193,6 +193,9 @@ int ObInfoSchemaKvCacheTable::set_diagnose_info(ObKVCacheInst *inst, ObDiagnoseT } else if (0 == strcmp(inst->status_.config_->cache_name_,"schema_cache")) { inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_CACHE_MISS); inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_CACHE_HIT)); + } else if (0 == strcmp(inst->status_.config_->cache_name_,"schema_history_cache")) { + inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_HISTORY_CACHE_MISS); + inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::SCHEMA_HISTORY_CACHE_HIT)); } else if (0 == strcmp(inst->status_.config_->cache_name_,"opt_table_stat_cache")) { inst->status_.total_miss_cnt_ = GLOBAL_EVENT_GET(ObStatEventIds::OPT_TABLE_STAT_CACHE_MISS); inst->status_.total_hit_cnt_.set(GLOBAL_EVENT_GET(ObStatEventIds::OPT_TABLE_STAT_CACHE_HIT)); diff --git a/src/share/cache/ob_cache_name_define.h b/src/share/cache/ob_cache_name_define.h index 2f37cfae5..9a2db5fd6 100644 --- a/src/share/cache/ob_cache_name_define.h +++ b/src/share/cache/ob_cache_name_define.h @@ -19,6 +19,7 @@ namespace share { const char *const OB_LOCATION_CACHE_NAME = "location_cache"; const char *const OB_SCHEMA_CACHE_NAME = "schema_cache"; +const char *const OB_SCHEMA_HISTORY_CACHE_NAME = "schema_history_cache"; const char *const OB_LS_LOCATION_CACHE_NAME = "ls_location_cache"; const char *const OB_TABLET_CACHE_NAME = "tablet_ls_cache"; const char *const OB_TABLET_TABLE_CACHE_NAME = "tablet_table_cache"; diff --git a/src/share/schema/ob_multi_version_schema_service.cpp b/src/share/schema/ob_multi_version_schema_service.cpp index c27713502..9fdc422a1 100644 --- a/src/share/schema/ob_multi_version_schema_service.cpp +++ b/src/share/schema/ob_multi_version_schema_service.cpp @@ -385,6 +385,7 @@ int ObMultiVersionSchemaService::get_schema(const ObSchemaMgr *mgr, int ret = OB_SUCCESS; const bool is_lazy = (NULL == mgr); uint64_t tenant_id = schema_status.tenant_id_; + bool update_history_cache = false; schema = NULL; if (TENANT_SCHEMA == schema_type && !is_sys_tenant(tenant_id)) { ret = OB_INVALID_ARGUMENT; @@ -473,51 +474,66 @@ int ObMultiVersionSchemaService::get_schema(const ObSchemaMgr *mgr, } if (OB_SUCC(ret) && !not_exist) { int i = 0; + int64_t precise_version = OB_INVALID_VERSION; for (; i < val.valid_cnt_; ++i) { if (val.versions_[i] <= schema_version) { break; } } if (i < val.valid_cnt_) { - const int64_t precise_version = val.versions_[i]; if (0 == i && val.is_deleted_) { not_exist = true; - LOG_INFO("schema has been deleted under specified version", K(ret), + LOG_INFO("schema has been deleted under specified version", KR(ret), K(key), K(val), K(schema_version), K(precise_version)); } else { // Access cache with accurate version - if (OB_FAIL(schema_cache_.get_schema(schema_type, - tenant_id, - schema_id, - precise_version, - handle, - schema))) { - if (ret != OB_ENTRY_NOT_EXIST) { - LOG_WARN("get schema from cache failed", K(tenant_id), K(key), - K(schema_version), K(precise_version), K(ret)); - } else { - ret = OB_SUCCESS; - } - } else { - // Accurate version hits, return directly - LOG_TRACE("precise version hit", K(tenant_id), K(key), - K(schema_version), K(precise_version), K(schema_id), - "schema_type", schema_type_str(schema_type)); - has_hit = true; - } + precise_version = val.versions_[i]; } } else if (schema_version < val.min_version_) { not_exist = true; - LOG_INFO("schema has not been created under specified version", K(ret), - K(tenant_id), K(key), K(val), K(schema_version)); + LOG_INFO("schema has not been created under specified version", + KR(ret), K(key), K(val), K(schema_version)); + } else if (schema_version == val.min_version_) { + precise_version = val.min_version_; + LOG_INFO("use min schema version as precise schema version", + KR(ret), K(key), K(val), K(schema_version)); } else { - // i >= cnt - // Older than the cached version, this situation is considered to be a very rare scenario, - // the "two" in the 28 theory - // directly uses the given schema_version to look up the table - LOG_INFO("precise version not founded since schema version is too old, " \ - "will retrieve it from inner table", K(tenant_id), K(key), K(val), - K(schema_version), "schema_type", schema_type_str(schema_type)); + // i >= cnt && schema_version > val.min_version_ + // try use discrete schema version relationship + if (OB_FAIL(schema_cache_.get_schema_history_cache( + schema_type, tenant_id, schema_id, schema_version, precise_version))) { + if (OB_ENTRY_NOT_EXIST != ret) { + LOG_WARN("get schema history cache failed", + KR(ret), K(schema_type), K(tenant_id), K(schema_id), K(schema_version)); + } else { + ret = OB_SUCCESS; + update_history_cache = true; + LOG_INFO("precise version not founded since schema version is too old, " \ + "will retrieve it from inner table", KR(ret), K(key), K(val), + K(schema_version), "schema_type", schema_type_str(schema_type)); + } + } + } + + // try use precise_version + if (OB_SUCC(ret) && precise_version > 0) { + if (OB_FAIL(schema_cache_.get_schema(schema_type, + tenant_id, + schema_id, + precise_version, + handle, + schema))) { + if (ret != OB_ENTRY_NOT_EXIST) { + LOG_WARN("get schema from cache failed", KR(ret), K(key), + K(schema_version), K(precise_version)); + } else { + ret = OB_SUCCESS; + } + } else { + LOG_TRACE("precise version hit", K(key), K(schema_version), K(precise_version), + K(tenant_id), K(schema_id), "schema_type", schema_type_str(schema_type)); + has_hit = true; + } } } } @@ -642,6 +658,11 @@ int ObMultiVersionSchemaService::get_schema(const ObSchemaMgr *mgr, schema))) { LOG_WARN("put and fetch schema failed", K(tenant_id), K(schema_type), K(schema_id), K(precise_version), K(schema_version), KR(ret)); + } else if (update_history_cache + && OB_FAIL(schema_cache_.put_schema_history_cache( + schema_type, tenant_id, schema_id, schema_version, precise_version))) { + LOG_WARN("fail to put schema history cache", KR(ret), K(schema_type), + K(tenant_id), K(schema_id), K(schema_version), K(precise_version)); } #ifndef NDEBUG diff --git a/src/share/schema/ob_schema_cache.cpp b/src/share/schema/ob_schema_cache.cpp index 2e282d0fa..f7055644d 100644 --- a/src/share/schema/ob_schema_cache.cpp +++ b/src/share/schema/ob_schema_cache.cpp @@ -251,6 +251,39 @@ int ObSchemaCacheValue::deep_copy(char *buf, return ret; } +ObSchemaHistoryCacheValue::ObSchemaHistoryCacheValue() + : schema_version_(OB_INVALID_VERSION) +{ +} + +ObSchemaHistoryCacheValue::ObSchemaHistoryCacheValue( + const int64_t schema_version) + : schema_version_(schema_version) +{ +} + +int64_t ObSchemaHistoryCacheValue::size() const +{ + return sizeof(*this); +} + +int ObSchemaHistoryCacheValue::deep_copy( + char *buf, + const int64_t buf_len, + ObIKVCacheValue *&value) const +{ + int ret = OB_SUCCESS; + ObSchemaHistoryCacheValue *schema_history_value = NULL; + if (OB_ISNULL(buf) || buf_len < size()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invaild arg", KR(ret), KP(buf), K(buf_len)); + } else { + schema_history_value = new (buf) ObSchemaHistoryCacheValue(schema_version_); + value = schema_history_value; + } + return ret; +} + ObTabletCacheKey::ObTabletCacheKey() : tenant_id_(OB_INVALID_TENANT_ID), tablet_id_(), @@ -379,11 +412,11 @@ int ObTabletCacheValue::deep_copy(char *buf, return ret; } - ObSchemaCache::ObSchemaCache() : mem_context_(nullptr), sys_cache_(), cache_(), + history_cache_(), is_inited_(false) { } @@ -464,6 +497,8 @@ int ObSchemaCache::init() const int64_t priority = 1001; if (OB_FAIL(cache_.init(OB_SCHEMA_CACHE_NAME, priority))) { LOG_WARN("init schema cache failed", KR(ret)); + } else if (OB_FAIL(history_cache_.init(OB_SCHEMA_HISTORY_CACHE_NAME, priority))) { + LOG_WARN("init schema history cache failed", K(ret)); } else if (OB_FAIL(tablet_cache_.init(OB_TABLET_TABLE_CACHE_NAME, priority))) { LOG_WARN("init tablet-table cache failed", KR(ret)); } else if (OB_FAIL(sys_cache_.create(OB_SCHEMA_CACHE_SYS_CACHE_MAP_BUCKET_NUM, @@ -585,7 +620,7 @@ int ObSchemaCache::get_schema( if (OB_SUCC(ret)) { if (OB_ISNULL(cache_value)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("cache_value is NULL", K(cache_value), K(ret)); + LOG_WARN("cache_value is NULL", KP(cache_value), K(ret)); } else { schema = cache_value->schema_; } @@ -626,18 +661,18 @@ int ObSchemaCache::put_sys_schema( K(deep_copy_size)); } else if (OB_ISNULL(kv_cache_value)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("cache value is NULL", KR(ret), K(kv_cache_value)); + LOG_WARN("cache value is NULL", KR(ret), KP(kv_cache_value)); } else { ObSchemaCacheValue *cache_value = static_cast(kv_cache_value); int overwrite_flag = 1; int hash_ret = sys_cache_.set_refactored(cache_key, cache_value, overwrite_flag); if (OB_SUCCESS == hash_ret) { LOG_DEBUG("put value to sys cache succeed", K(hash_ret), K(cache_key), - K(*cache_value)); + KPC(cache_value)); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("put value to sys cache failed", KR(ret), K(hash_ret), - K(cache_key), K(*cache_value)); + K(cache_key), KPC(cache_value)); } } } @@ -771,6 +806,71 @@ int ObSchemaCache::put_tablet_cache( return ret; } +int ObSchemaCache::get_schema_history_cache( + const ObSchemaType schema_type, + const uint64_t tenant_id, + const uint64_t schema_id, + const int64_t schema_version, + int64_t &precise_schema_version) +{ + int ret = OB_SUCCESS; + precise_schema_version = OB_INVALID_VERSION; + if (OB_UNLIKELY(!check_inner_stat())) { + ret = OB_INNER_STAT_ERROR; + LOG_WARN("inner stat error", KR(ret)); + } else if (OB_UNLIKELY(!is_valid_key(schema_type, tenant_id, schema_id, schema_version))) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KR(ret), K(schema_type), K(tenant_id), K(schema_id), K(schema_version)); + } else { + ObSchemaCacheKey cache_key(schema_type, tenant_id, schema_id, schema_version); + const ObSchemaHistoryCacheValue *cache_value = NULL; + ObKVCacheHandle handle; + if (OB_FAIL(history_cache_.get(cache_key, cache_value, handle))) { + if (OB_ENTRY_NOT_EXIST != ret) { + LOG_WARN("fail to get schema history value", KR(ret), K(cache_key)); + } + EVENT_INC(ObStatEventIds::SCHEMA_HISTORY_CACHE_MISS); + } else if (OB_ISNULL(cache_value)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cache_value is null", KR(ret), KP(cache_value)); + } else { + precise_schema_version = cache_value->schema_version_; + EVENT_INC(ObStatEventIds::SCHEMA_HISTORY_CACHE_HIT); + LOG_TRACE("get schema history cache succeed", KR(ret), K(cache_key)); + } + } + return ret; +} + +int ObSchemaCache::put_schema_history_cache( + const ObSchemaType schema_type, + const uint64_t tenant_id, + const uint64_t schema_id, + const int64_t schema_version, + const int64_t precise_schema_version) +{ + int ret = OB_SUCCESS; + if (OB_UNLIKELY(!check_inner_stat())) { + ret = OB_INNER_STAT_ERROR; + LOG_WARN("inner stat error", KR(ret)); + } else if (OB_UNLIKELY( + !is_valid_key(schema_type, tenant_id, schema_id, schema_version) + || precise_schema_version <= 0)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", KR(ret), K(schema_type), K(tenant_id), K(schema_id), + K(schema_version), K(precise_schema_version)); + } else { + ObSchemaCacheKey cache_key(schema_type, tenant_id, schema_id, schema_version); + ObSchemaHistoryCacheValue cache_value(precise_schema_version); + if (OB_FAIL(history_cache_.put(cache_key, cache_value))) { + LOG_WARN("put value to schema cache failed", KR(ret), K(cache_key), K(cache_value)); + } else { + LOG_TRACE("put schema history cache succeed", KR(ret), K(cache_key), K(cache_value)); + } + } + return ret; +} + ObSchemaFetcher::ObSchemaFetcher() : schema_service_(NULL), sql_client_(NULL), diff --git a/src/share/schema/ob_schema_cache.h b/src/share/schema/ob_schema_cache.h index 31ae21042..a314fc12b 100644 --- a/src/share/schema/ob_schema_cache.h +++ b/src/share/schema/ob_schema_cache.h @@ -86,6 +86,21 @@ public: const ObSchema *schema_; }; +class ObSchemaHistoryCacheValue : public common::ObIKVCacheValue +{ +public: + ObSchemaHistoryCacheValue(); + ObSchemaHistoryCacheValue(const int64_t schema_version); + virtual ~ObSchemaHistoryCacheValue() {} + virtual int64_t size() const; + virtual int deep_copy(char *buf, + int64_t buf_len, + ObIKVCacheValue *&value) const; + TO_STRING_KV(K_(schema_version)); + + int64_t schema_version_; +}; + class ObTabletCacheKey : public common::ObIKVCacheKey { public: @@ -161,6 +176,16 @@ public: const ObSchema &schema, common::ObKVCacheHandle &handle, const ObSchema *&new_schema); + int get_schema_history_cache(const ObSchemaType schema_type, + const uint64_t tenant_id, + const uint64_t schema_id, + const int64_t schema_version, + int64_t &precise_schema_version); + int put_schema_history_cache(const ObSchemaType schema_type, + const uint64_t tenant_id, + const uint64_t schema_id, + const int64_t schema_version, + const int64_t precise_schema_version); const ObTableSchema *get_all_core_table() const; const ObSimpleTenantSchema *get_simple_gts_tenant() const; const ObTenantSchema *get_full_gts_tenant() const; @@ -198,11 +223,13 @@ private: const ObSchemaCacheValue*, common::hash::ReadWriteDefendMode> NoSwapCache; typedef common::ObKVCache KVCache; + typedef common::ObKVCache HistoryCache; typedef common::ObKVCache TabletCache; lib::MemoryContext mem_context_; NoSwapCache sys_cache_; KVCache cache_; + HistoryCache history_cache_; bool is_inited_; ObTableSchema all_core_table_; ObSimpleTenantSchema simple_gts_tenant_;