[CP] Add schema history cache

This commit is contained in:
tino247 2023-07-17 07:48:20 +00:00 committed by ob-robot
parent b041a0bf20
commit 97d8e0fc71
6 changed files with 190 additions and 35 deletions

View File

@ -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")

View File

@ -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));

View File

@ -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";

View File

@ -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

View File

@ -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<ObSchemaCacheValue *>(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),

View File

@ -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<ObSchemaCacheKey, ObSchemaCacheValue> KVCache;
typedef common::ObKVCache<ObSchemaCacheKey, ObSchemaHistoryCacheValue> HistoryCache;
typedef common::ObKVCache<ObTabletCacheKey, ObTabletCacheValue> TabletCache;
lib::MemoryContext mem_context_;
NoSwapCache sys_cache_;
KVCache cache_;
HistoryCache history_cache_;
bool is_inited_;
ObTableSchema all_core_table_;
ObSimpleTenantSchema simple_gts_tenant_;