fix sql plan manger memory bug

This commit is contained in:
zzg19950727 2023-02-10 06:47:16 +00:00 committed by ob-robot
parent f7a3157781
commit 5ae3b0664f
15 changed files with 936 additions and 965 deletions

View File

@ -92,7 +92,6 @@
#include "share/deadlock/ob_deadlock_detector_mgr.h"
#include "lib/mysqlclient/ob_tenant_oci_envs.h"
#include "sql/monitor/ob_sql_plan_manager.h"
#include "sql/monitor/ob_plan_real_info_manager.h"
#include "sql/udr/ob_udr_mgr.h"
#include "storage/blocksstable/ob_shared_macro_block_manager.h"
#include "storage/tx_storage/ob_tablet_gc_service.h"
@ -362,7 +361,6 @@ int ObMultiTenant::init(ObAddr myaddr,
MTL_BIND2(mtl_new_default, ObSharedMacroBlockMgr::mtl_init, mtl_start_default, mtl_stop_default, mtl_wait_default, mtl_destroy_default);
MTL_BIND(ObFLTSpanMgr::mtl_init, ObFLTSpanMgr::mtl_destroy);
MTL_BIND(ObSqlPlanMgr::mtl_init, ObSqlPlanMgr::mtl_destroy);
MTL_BIND(ObPlanRealInfoMgr::mtl_init, ObPlanRealInfoMgr::mtl_destroy);
MTL_BIND(common::sqlclient::ObTenantOciEnvs::mtl_init, common::sqlclient::ObTenantOciEnvs::mtl_destroy);
MTL_BIND2(mtl_new_default, ObPlanCache::mtl_init, nullptr, ObPlanCache::mtl_stop, nullptr, mtl_destroy_default);
MTL_BIND2(mtl_new_default, ObPsCache::mtl_init, nullptr, ObPsCache::mtl_stop, nullptr, mtl_destroy_default);

View File

@ -4,6 +4,7 @@
// this file defines implementation of __all_virtual_plan_real_info
#include "sql/monitor/ob_plan_real_info_manager.h"
#include "sql/monitor/ob_sql_plan_manager.h"
#include "ob_all_virtual_plan_real_info.h"
#include "observer/omt/ob_multi_tenant.h"
#include "observer/ob_server_struct.h"
@ -202,6 +203,7 @@ int ObAllVirtualPlanRealInfo::inner_get_next_row(common::ObNewRow *&row)
SERVER_LOG(WARN, "failed to allocate memory", K(ret));
} else {
with_tenant_ctx_ = new(buff) ObTenantSpaceFetcher(t_id);
ObSqlPlanMgr *sql_plan_mgr = NULL;
if (OB_FAIL(with_tenant_ctx_->get_ret())) {
// 如果指定tenant id查询, 且当前机器没有该租户资源时, 获取
// tenant space会报OB_TENANT_NOT_IN_SERVER, 此时需要忽略该报
@ -210,8 +212,11 @@ int ObAllVirtualPlanRealInfo::inner_get_next_row(common::ObNewRow *&row)
ret = OB_SUCCESS;
continue;
}
} else if (OB_ISNULL(sql_plan_mgr=with_tenant_ctx_->entity().get_tenant()->get<ObSqlPlanMgr*>())) {
plan_real_info_mgr_ = nullptr;
SERVER_LOG(DEBUG, "unexpect null sql plan manager", K(ret));
} else {
plan_real_info_mgr_ = with_tenant_ctx_->entity().get_tenant()->get<ObPlanRealInfoMgr *>();
plan_real_info_mgr_ = sql_plan_mgr->get_plan_real_info_mgr();
}
}

View File

@ -32,17 +32,14 @@ int ObAllVirtualPlanTable::inner_reset()
{
int ret = OB_SUCCESS;
if (nullptr == plan_table_mgr_) {
ret = OB_NOT_INIT;
SERVER_LOG(DEBUG, "plan table manager doest not exist", K(ret));
//do nothing
} else {
start_id_ = INT64_MIN;
end_id_ = INT64_MAX;
ObRaQueue::Ref ref;
int64_t start_idx = plan_table_mgr_->get_start_idx();
int64_t end_idx = plan_table_mgr_->get_end_idx();
start_id_ = MAX(start_id_, start_idx);
end_id_ = MIN(end_id_, end_idx);
plan_table_mgr_->revert(&ref);
if (start_id_ >= end_id_) {
SERVER_LOG(DEBUG, "sql_plan_mgr_ iter end", K(start_id_), K(end_id_));
} else if (is_reverse_scan()) {
@ -70,18 +67,18 @@ int ObAllVirtualPlanTable::inner_open()
int ObAllVirtualPlanTable::inner_get_next_row(common::ObNewRow *&row)
{
int ret = OB_SUCCESS;
ObRaQueue::Ref ref;
void *rec = NULL;
if (NULL == allocator_ ||
OB_ISNULL(plan_table_mgr_)) {
if (NULL == allocator_) {
ret = OB_NOT_INIT;
SERVER_LOG(WARN, "invalid argument", KP(allocator_), K(ret));
} else if (cur_id_ < start_id_ ||
} else if (nullptr == plan_table_mgr_ ||
cur_id_ < start_id_ ||
cur_id_ >= end_id_) {
ret = OB_ITER_END;
}
//fetch next record
if (OB_SUCC(ret)) {
ObRaQueue::Ref ref;
do {
ref.reset();
ret = plan_table_mgr_->get(cur_id_, rec, &ref);
@ -109,6 +106,7 @@ int ObAllVirtualPlanTable::inner_get_next_row(common::ObNewRow *&row)
} else {
//finish fetch one row
row = &cur_row_;
plan_table_mgr_->revert(&ref);
SERVER_LOG(DEBUG, "get next row succ", K(cur_id_));
}
}

View File

@ -14,7 +14,7 @@ namespace oceanbase
{
namespace sql
{
class ObSqlPlanMgr;
class ObPlanItemMgr;
class ObSqlPlanItemRecord;
}
namespace common
@ -37,7 +37,7 @@ public:
int inner_reset();
int inner_open();
void set_plan_table_mgr(sql::ObSqlPlanMgr *plan_table_mgr)
void set_plan_table_mgr(sql::ObPlanItemMgr *plan_table_mgr)
{ plan_table_mgr_ = plan_table_mgr; }
virtual void reset();
virtual int inner_get_next_row(common::ObNewRow *&row);
@ -90,7 +90,7 @@ private:
};
DISALLOW_COPY_AND_ASSIGN(ObAllVirtualPlanTable);
sql::ObSqlPlanMgr *plan_table_mgr_;
sql::ObPlanItemMgr *plan_table_mgr_;
int64_t start_id_;
int64_t end_id_;
int64_t cur_id_;

View File

@ -152,7 +152,7 @@ int ObAllVirtualSqlPlan::check_ip_and_port(bool &is_valid)
int ObAllVirtualSqlPlan::inner_get_next_row(common::ObNewRow *&row)
{
int ret = OB_SUCCESS;
ObSqlPlanMgr *prev_mgr = sql_plan_mgr_;
ObPlanItemMgr *prev_mgr = sql_plan_mgr_;
if (NULL == allocator_) {
ret = OB_NOT_INIT;
SERVER_LOG(WARN, "invalid argument", KP(allocator_), K(ret));
@ -202,6 +202,7 @@ int ObAllVirtualSqlPlan::inner_get_next_row(common::ObNewRow *&row)
SERVER_LOG(WARN, "failed to allocate memory", K(ret));
} else {
with_tenant_ctx_ = new(buff) ObTenantSpaceFetcher(t_id);
ObSqlPlanMgr *sql_plan_mgr = NULL;
if (OB_FAIL(with_tenant_ctx_->get_ret())) {
// 如果指定tenant id查询, 且当前机器没有该租户资源时, 获取
// tenant space会报OB_TENANT_NOT_IN_SERVER, 此时需要忽略该报
@ -210,8 +211,11 @@ int ObAllVirtualSqlPlan::inner_get_next_row(common::ObNewRow *&row)
ret = OB_SUCCESS;
continue;
}
} else if (OB_ISNULL(sql_plan_mgr=with_tenant_ctx_->entity().get_tenant()->get<ObSqlPlanMgr *>())) {
sql_plan_mgr_ = nullptr;
SERVER_LOG(DEBUG, "unexpect null plan manager", K(ret));
} else {
sql_plan_mgr_ = with_tenant_ctx_->entity().get_tenant()->get<ObSqlPlanMgr *>();
sql_plan_mgr_ = sql_plan_mgr->get_plan_item_mgr();
}
}

View File

@ -14,7 +14,7 @@ namespace oceanbase
{
namespace sql
{
class ObSqlPlanMgr;
class ObPlanItemMgr;
class ObSqlPlanItemRecord;
}
namespace common
@ -102,7 +102,7 @@ private:
const static int64_t ROWKEY_COUNT = 4;
DISALLOW_COPY_AND_ASSIGN(ObAllVirtualSqlPlan);
sql::ObSqlPlanMgr *sql_plan_mgr_;
sql::ObPlanItemMgr *sql_plan_mgr_;
int64_t start_id_;
int64_t end_id_;
int64_t cur_id_;

View File

@ -44,7 +44,6 @@ namespace sql {
class ObDASIDService;
class ObFLTSpanMgr;
class ObSqlPlanMgr;
class ObPlanRealInfoMgr;
class ObUDRMgr;
class ObPlanCache;
class ObPsCache;
@ -238,7 +237,6 @@ using ObPartTransCtxObjPool = common::ObServerObjectPool<transaction::ObPartTran
sql::ObUDRMgr*, \
sql::ObFLTSpanMgr*, \
sql::ObSqlPlanMgr*, \
sql::ObPlanRealInfoMgr*, \
ObTestModule*, \
oceanbase::common::sqlclient::ObTenantOciEnvs* \
)

View File

@ -17,7 +17,7 @@
#include "ob_operator_factory.h"
#include "sql/engine/ob_exec_context.h"
#include "common/ob_smart_call.h"
#include "sql/monitor/ob_plan_real_info_manager.h"
#include "sql/monitor/ob_sql_plan_manager.h"
namespace oceanbase
{
@ -899,7 +899,11 @@ int ObOperator::submit_op_monitor_node()
LOG_DEBUG("debug monitor", K(spec_.id_));
}
}
ObPlanRealInfoMgr *plan_info = MTL(ObPlanRealInfoMgr*);
ObSqlPlanMgr *sql_plan_mgr = MTL(ObSqlPlanMgr*);
ObPlanRealInfoMgr *plan_info = NULL;
if (NULL != sql_plan_mgr) {
plan_info = sql_plan_mgr->get_plan_real_info_mgr();
}
if (plan_info && spec_.plan_ && spec_.plan_->need_record_plan_info()) {
IGNORE_RETURN plan_info->handle_plan_info(spec_.id_,
spec_.plan_->get_sql_id_string(),

View File

@ -7,7 +7,6 @@
#define USING_LOG_PREFIX SQL
#include "share/diagnosis/ob_sql_plan_monitor_node_list.h"
#include "lib/allocator/ob_concurrent_fifo_allocator.h"
#include "lib/compress/zlib/zlib_src/zlib.h"
#include "sql/session/ob_sql_session_info.h"
#include "lib/thread/thread_mgr.h"
#include "common/object/ob_object.h"
@ -66,14 +65,11 @@ void ObPlanRealInfoRecord::destroy()
}
}
ObPlanRealInfoMgr::ObPlanRealInfoMgr()
:allocator_(),
task_(),
ObPlanRealInfoMgr::ObPlanRealInfoMgr(ObConcurrentFIFOAllocator *allocator)
:allocator_(allocator),
queue_(),
destroyed_(false),
inited_(false),
tenant_id_(OB_INVALID_TENANT_ID),
tg_id_(-1)
inited_(false)
{
}
@ -94,27 +90,9 @@ int ObPlanRealInfoMgr::init(uint64_t tenant_id,
queue_size,
tenant_id))) {
SERVER_LOG(WARN, "Failed to init ObMySQLRequestQueue", K(ret));
} else if (OB_FAIL(TG_CREATE_TENANT(lib::TGDefIDs::ReqMemEvict,
tg_id_))) {
SERVER_LOG(WARN, "create failed", K(ret));
} else if (OB_FAIL(TG_START(tg_id_))) {
SERVER_LOG(WARN, "init timer fail", K(ret));
} else if (OB_FAIL(allocator_.init(SQL_PLAN_PAGE_SIZE,
ObModIds::OB_SQL_PLAN,
tenant_id,
INT64_MAX))) {
SERVER_LOG(WARN, "failed to init allocator", K(ret));
} else {
//check FIFO mem used and plan real info every 1 seconds
if (OB_FAIL(task_.init(this))) {
SERVER_LOG(WARN, "fail to init plan real info timer task", K(ret));
} else if (OB_FAIL(TG_SCHEDULE(tg_id_, task_, EVICT_INTERVAL, true))) {
SERVER_LOG(WARN, "start eliminate task failed", K(ret));
} else {
tenant_id_ = tenant_id;
inited_ = true;
destroyed_ = false;
}
inited_ = true;
destroyed_ = false;
}
if ((OB_FAIL(ret)) && (!inited_)) {
destroy();
@ -125,10 +103,8 @@ int ObPlanRealInfoMgr::init(uint64_t tenant_id,
void ObPlanRealInfoMgr::destroy()
{
if (!destroyed_) {
TG_DESTROY(tg_id_);
clear_queue();
queue_.destroy();
allocator_.destroy();
inited_ = false;
destroyed_ = true;
}
@ -168,7 +144,7 @@ int ObPlanRealInfoMgr::handle_plan_info(int64_t id,
real_time = last_row_time - open_time;
}
record = new(buf)ObPlanRealInfoRecord();
record->allocator_ = &allocator_;
record->allocator_ = allocator_;
record->data_.id_ = id;
record->data_.plan_id_ = plan_id;
record->data_.plan_hash_ = plan_hash;
@ -200,19 +176,24 @@ int ObPlanRealInfoMgr::handle_plan_info(int64_t id,
ObConcurrentFIFOAllocator *ObPlanRealInfoMgr::get_allocator()
{
return &allocator_;
return allocator_;
}
void* ObPlanRealInfoMgr::alloc(const int64_t size)
{
void * ret = allocator_.alloc(size);
void *ret = NULL;
if (allocator_ != NULL) {
ret = allocator_->alloc(size);
}
return ret;
}
void ObPlanRealInfoMgr::free(void *ptr)
{
allocator_.free(ptr);
ptr = NULL;
if (allocator_ != NULL) {
allocator_->free(ptr);
ptr = NULL;
}
}
int ObPlanRealInfoMgr::get(const int64_t idx, void *&record, Ref* ref)
@ -230,14 +211,15 @@ int ObPlanRealInfoMgr::revert(Ref* ref)
return OB_SUCCESS;
}
int ObPlanRealInfoMgr::release_old(int64_t limit)
int64_t ObPlanRealInfoMgr::release_old(int64_t limit)
{
void* req = NULL;
int64_t count = 0;
while(count++ < limit && NULL != (req = queue_.pop())) {
free(req);
while(count < limit && NULL != (req = queue_.pop())) {
free(req);
++count;
}
return OB_SUCCESS;
return count;
}
void ObPlanRealInfoMgr::clear_queue()
@ -245,11 +227,6 @@ void ObPlanRealInfoMgr::clear_queue()
(void)release_old(INT64_MAX);
}
uint64_t ObPlanRealInfoMgr::get_tenant_id() const
{
return tenant_id_;
}
bool ObPlanRealInfoMgr::is_valid() const
{
return inited_ && !destroyed_;
@ -267,257 +244,432 @@ int64_t ObPlanRealInfoMgr::get_end_idx() const
int64_t ObPlanRealInfoMgr::get_size_used()
{
return (int64_t)(queue_.get_push_idx() - queue_.get_pop_idx());
return (int64_t)queue_.get_size();
}
int64_t ObPlanRealInfoMgr::get_size()
int64_t ObPlanRealInfoMgr::get_capacity()
{
return (int64_t)queue_.get_capacity();
}
ObSqlPlanItem::ObSqlPlanItem()
{
reset();
}
ObSqlPlanItem::~ObSqlPlanItem()
{
}
void ObSqlPlanItem::reset()
{
plan_id_ = 0;
db_id_ = 0;
sql_id_ = NULL;
sql_id_len_ = 0;
plan_hash_ = 0;
gmt_create_ = 0;
operation_ = NULL;
operation_len_ = 0;
options_ = NULL;
options_len_ = 0;
object_node_ = NULL;
object_node_len_ = 0;
object_id_ = 0;
object_owner_ = NULL;
object_owner_len_ = 0;
object_name_ = NULL;
object_name_len_ = 0;
object_alias_ = NULL;
object_alias_len_ = 0;
object_type_ = NULL;
object_type_len_ = 0;
optimizer_ = NULL;
optimizer_len_ = 0;
id_ = 0;
parent_id_ = 0;
depth_ = 0;
position_ = 0;
is_last_child_ = false;
search_columns_ = 0;
cost_ = 0;
cardinality_ = 0;
bytes_ = 0;
rowset_ = 1;
other_tag_ = NULL;
other_tag_len_ = 0;
partition_start_ = NULL;
partition_start_len_ = 0;
partition_stop_ = NULL;
partition_stop_len_ = 0;
partition_id_ = 0;
other_ = NULL;
other_len_ = 0;
distribution_ = NULL;
distribution_len_ = 0;
cpu_cost_ = 0;
io_cost_ = 0;
temp_space_ = 0;
access_predicates_ = NULL;
access_predicates_len_ = 0;
filter_predicates_ = NULL;
filter_predicates_len_ = 0;
startup_predicates_ = NULL;
startup_predicates_len_ = 0;
projection_ = NULL;
projection_len_ = 0;
special_predicates_ = NULL;
special_predicates_len_ = 0;
time_ = 0;
qblock_name_ = NULL;
qblock_name_len_ = 0;
remarks_ = NULL;
remarks_len_ = 0;
other_xml_ = NULL;
other_xml_len_ = 0;
}
int64_t ObSqlPlanItem::get_extra_size() const
{
return sql_id_len_ +
operation_len_ +
options_len_ +
object_node_len_ +
object_owner_len_ +
object_name_len_ +
object_alias_len_ +
object_type_len_ +
optimizer_len_ +
other_tag_len_ +
partition_start_len_ +
partition_stop_len_ +
other_len_ +
distribution_len_ +
access_predicates_len_ +
filter_predicates_len_ +
startup_predicates_len_ +
projection_len_ +
special_predicates_len_ +
qblock_name_len_ +
remarks_len_ +
other_xml_len_;
}
ObSqlPlanItemRecord::ObSqlPlanItemRecord()
:allocator_(NULL)
{
}
ObSqlPlanItemRecord::~ObSqlPlanItemRecord()
{
destroy();
}
void ObSqlPlanItemRecord::destroy()
{
if (NULL != allocator_) {
allocator_->free(this);
}
}
ObPlanItemMgr::ObPlanItemMgr(ObConcurrentFIFOAllocator *allocator)
:allocator_(allocator),
queue_(),
plan_id_increment_(0),
destroyed_(false),
inited_(false)
{
}
ObPlanItemMgr::~ObPlanItemMgr()
{
if (inited_) {
destroy();
}
}
int ObPlanItemMgr::init(uint64_t tenant_id,
const int64_t queue_size)
{
int ret = OB_SUCCESS;
if (inited_) {
ret = OB_INIT_TWICE;
} else if (OB_FAIL(queue_.init(ObModIds::OB_SQL_PLAN,
queue_size,
tenant_id))) {
SERVER_LOG(WARN, "Failed to init ObMySQLRequestQueue", K(ret));
} else {
inited_ = true;
destroyed_ = false;
}
if ((OB_FAIL(ret)) && (!inited_)) {
destroy();
}
return ret;
}
void ObPlanItemMgr::destroy()
{
if (!destroyed_) {
clear_queue();
queue_.destroy();
inited_ = false;
destroyed_ = true;
}
}
int ObPlanItemMgr::handle_plan_item(const ObSqlPlanItem &plan_item)
{
int ret = OB_SUCCESS;
ObSqlPlanItemRecord *record = NULL;
if (!inited_) {
ret = OB_NOT_INIT;
} else {
char *buf = NULL;
//alloc mem from allocator
int64_t pos = sizeof(ObSqlPlanItemRecord);
int64_t total_size = sizeof(ObSqlPlanItemRecord) +
plan_item.get_extra_size();
if (NULL == (buf = (char*)alloc(total_size))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
if (REACH_TIME_INTERVAL(100 * 1000)) {
SERVER_LOG(WARN, "alloc mem failed", K(total_size), K(ret));
}
} else {
record = new(buf)ObSqlPlanItemRecord();
record->allocator_ = allocator_;
record->data_ = plan_item;
#define DEEP_COPY_DATA(value) \
do { \
if (pos + plan_item.value##len_ > total_size) { \
ret = OB_ERR_UNEXPECTED; \
LOG_WARN("unexpect record size", K(pos), K(plan_item.value##len_), \
K(total_size), K(ret)); \
} else if ((plan_item.value##len_ > 0) && (NULL != plan_item.value)) { \
MEMCPY(buf + pos, plan_item.value, plan_item.value##len_); \
record->data_.value = buf + pos; \
pos += plan_item.value##len_; \
} else { \
record->data_.value = buf + pos; \
} \
} while(0);
DEEP_COPY_DATA(sql_id_);
DEEP_COPY_DATA(operation_);
DEEP_COPY_DATA(options_);
DEEP_COPY_DATA(object_node_);
DEEP_COPY_DATA(object_owner_);
DEEP_COPY_DATA(object_name_);
DEEP_COPY_DATA(object_alias_);
DEEP_COPY_DATA(object_type_);
DEEP_COPY_DATA(optimizer_);
DEEP_COPY_DATA(other_tag_);
DEEP_COPY_DATA(partition_start_);
DEEP_COPY_DATA(partition_stop_);
DEEP_COPY_DATA(other_);
DEEP_COPY_DATA(distribution_);
DEEP_COPY_DATA(access_predicates_);
DEEP_COPY_DATA(filter_predicates_);
DEEP_COPY_DATA(startup_predicates_);
DEEP_COPY_DATA(projection_);
DEEP_COPY_DATA(special_predicates_);
DEEP_COPY_DATA(qblock_name_);
DEEP_COPY_DATA(remarks_);
DEEP_COPY_DATA(other_xml_);
}
//push into queue
if (OB_SUCC(ret)) {
int64_t req_id = 0;
if (OB_FAIL(queue_.push(record, req_id))) {
if (REACH_TIME_INTERVAL(2 * 1000 * 1000)) {
SERVER_LOG(WARN, "push into queue failed", K(ret));
}
free(record);
record = NULL;
}
}
}
return ret;
}
int ObPlanItemMgr::get_plan(int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan)
{
int ret = OB_SUCCESS;
plan.reuse();
int64_t start_idx = get_start_idx();
int64_t end_idx = get_end_idx();
void *rec = NULL;
Ref ref;
for (int64_t cur_id=start_idx;
(OB_ENTRY_NOT_EXIST == ret || OB_SUCCESS == ret) && cur_id < end_idx;
++cur_id) {
ref.reset();
ret = get(cur_id, rec, &ref);
if (OB_SUCC(ret) && NULL != rec) {
ObSqlPlanItemRecord *record = static_cast<ObSqlPlanItemRecord*>(rec);
if (record->data_.plan_id_ != plan_id) {
//do nothing
} else if (OB_FAIL(plan.push_back(&record->data_))) {
LOG_WARN("failed to push back plan item", K(ret));
}
}
if (ref.idx_ != -1) {
revert(&ref);
}
}
return ret;
}
int ObPlanItemMgr::get_plan(const ObString &sql_id,
int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan)
{
int ret = OB_SUCCESS;
plan.reuse();
int64_t start_idx = get_start_idx();
int64_t end_idx = get_end_idx();
void *rec = NULL;
Ref ref;
for (int64_t cur_id=start_idx;
(OB_ENTRY_NOT_EXIST == ret || OB_SUCCESS == ret) && cur_id < end_idx;
++cur_id) {
ref.reset();
ret = get(cur_id, rec, &ref);
if (OB_SUCC(ret) && NULL != rec) {
ObSqlPlanItemRecord *record = static_cast<ObSqlPlanItemRecord*>(rec);
if (record->data_.plan_id_ != plan_id ||
sql_id.case_compare(ObString(record->data_.sql_id_len_,record->data_.sql_id_)) != 0) {
//do nothing
} else if (OB_FAIL(plan.push_back(&record->data_))) {
LOG_WARN("failed to push back plan item", K(ret));
}
}
if (ref.idx_ != -1) {
revert(&ref);
}
}
return ret;
}
int ObPlanItemMgr::get_plan_by_hash(const ObString &sql_id,
uint64_t plan_hash,
ObIArray<ObSqlPlanItem*> &plan)
{
int ret = OB_SUCCESS;
plan.reuse();
int64_t start_idx = get_start_idx();
int64_t end_idx = get_end_idx();
void *rec = NULL;
Ref ref;
for (int64_t cur_id=start_idx;
(OB_ENTRY_NOT_EXIST == ret || OB_SUCCESS == ret) && cur_id < end_idx;
++cur_id) {
ref.reset();
ret = get(cur_id, rec, &ref);
if (OB_SUCC(ret) && NULL != rec) {
ObSqlPlanItemRecord *record = static_cast<ObSqlPlanItemRecord*>(rec);
if (record->data_.plan_hash_ != plan_hash ||
sql_id.case_compare(ObString(record->data_.sql_id_len_,record->data_.sql_id_)) != 0) {
//do nothing
} else if (OB_FAIL(plan.push_back(&record->data_))) {
LOG_WARN("failed to push back plan item", K(ret));
}
}
if (ref.idx_ != -1) {
revert(&ref);
}
}
return ret;
}
ObConcurrentFIFOAllocator *ObPlanItemMgr::get_allocator()
{
return allocator_;
}
void* ObPlanItemMgr::alloc(const int64_t size)
{
void *ret = NULL;
if (allocator_ != NULL) {
ret = allocator_->alloc(size);
}
return ret;
}
void ObPlanItemMgr::free(void *ptr)
{
if (allocator_ != NULL) {
allocator_->free(ptr);
ptr = NULL;
}
}
int ObPlanItemMgr::get(const int64_t idx, void *&record, Ref* ref)
{
int ret = OB_SUCCESS;
if (NULL == (record = queue_.get(idx, ref))) {
ret = OB_ENTRY_NOT_EXIST;
}
return ret;
}
int ObPlanItemMgr::revert(Ref* ref)
{
queue_.revert(ref);
return OB_SUCCESS;
}
int64_t ObPlanItemMgr::release_old(int64_t limit)
{
void* req = NULL;
int64_t count = 0;
while(count < limit && NULL != (req = queue_.pop())) {
free(req);
++count;
}
return count;
}
void ObPlanItemMgr::clear_queue()
{
(void)release_old(INT64_MAX);
}
bool ObPlanItemMgr::is_valid() const
{
return inited_ && !destroyed_;
}
int64_t ObPlanItemMgr::get_start_idx() const
{
return (int64_t)queue_.get_pop_idx();
}
int64_t ObPlanItemMgr::get_end_idx() const
{
return (int64_t)queue_.get_push_idx();
}
int64_t ObPlanItemMgr::get_size_used()
{
return (int64_t)queue_.get_size();
}
int ObPlanRealInfoMgr::get_mem_limit(uint64_t tenant_id, int64_t &mem_limit)
int64_t ObPlanItemMgr::get_capacity()
{
int ret = OB_SUCCESS;
int64_t tenant_mem_limit = lib::get_tenant_memory_limit(tenant_id);
// default mem limit
mem_limit = static_cast<int64_t>(SQL_PLAN_MEM_FACTOR * tenant_mem_limit);
// get mem_percentage from session info
ObArenaAllocator alloc;
ObObj obj_val;
int64_t mem_pct = 0;
if (OB_FAIL(ObBasicSessionInfo::get_global_sys_variable(tenant_id,
alloc,
ObDataTypeCastParams(),
ObString(share::OB_SV_SQL_PLAN_MEMORY_PERCENTAGE),
obj_val))) {
LOG_WARN("failed to get global sys variable", K(ret));
} else if (OB_FAIL(obj_val.get_int(mem_pct))) {
LOG_WARN("failed to get int", K(ret), K(obj_val));
} else if (mem_pct < 0 || mem_pct > 100) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid value of plan real info mem percentage", K(ret), K(mem_pct));
} else {
mem_limit = static_cast<int64_t>(tenant_mem_limit * mem_pct / 100.0);
LOG_DEBUG("tenant plan real info memory limit",
K(tenant_id), K(tenant_mem_limit), K(mem_pct), K(mem_limit));
}
return ret;
return (int64_t)queue_.get_capacity();
}
int ObPlanRealInfoMgr::mtl_init(ObPlanRealInfoMgr* &plan_real_info_mgr)
int64_t ObPlanItemMgr::get_next_plan_id()
{
int ret = OB_SUCCESS;
plan_real_info_mgr = OB_NEW(ObPlanRealInfoMgr, ObModIds::OB_SQL_PLAN);
if (nullptr == plan_real_info_mgr) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc memory for ObPlanRealInfoMgr", K(ret));
} else {
int64_t queue_size = lib::is_mini_mode() ?
MINI_MODE_MAX_QUEUE_SIZE : MAX_QUEUE_SIZE;
uint64_t tenant_id = lib::current_resource_owner_id();
if (OB_FAIL(plan_real_info_mgr->init(tenant_id,
queue_size))) {
LOG_WARN("failed to init request manager", K(ret));
}
}
if (OB_FAIL(ret) && plan_real_info_mgr != nullptr) {
// cleanup
ob_delete(plan_real_info_mgr);
plan_real_info_mgr = nullptr;
}
return ret;
return ++plan_id_increment_;
}
void ObPlanRealInfoMgr::mtl_destroy(ObPlanRealInfoMgr* &plan_real_info_mgr)
int64_t ObPlanItemMgr::get_last_plan_id()
{
if (plan_real_info_mgr != nullptr) {
ob_delete(plan_real_info_mgr);
plan_real_info_mgr = nullptr;
}
}
ObPlanRealInfoEliminateTask::ObPlanRealInfoEliminateTask()
:plan_real_info_manager_(NULL),
config_mem_limit_(0)
{
}
ObPlanRealInfoEliminateTask::~ObPlanRealInfoEliminateTask()
{
}
int ObPlanRealInfoEliminateTask::init(const ObPlanRealInfoMgr *plan_real_info_manager)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(plan_real_info_manager)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(plan_real_info_manager_), K(ret));
} else {
plan_real_info_manager_ = const_cast<ObPlanRealInfoMgr*>(plan_real_info_manager);
// can't call ObPlanRealInfoMgr::get_mem_limit for now, tenant not inited
// set config_mem_limit_ to 64M
config_mem_limit_ = 64 * 1024 * 1024; // 64M
disable_timeout_check();
}
return ret;
}
//mem_limit = tenant_mem_limit * ob_sql_plan_percentage
int ObPlanRealInfoEliminateTask::check_config_mem_limit(bool &is_change)
{
int ret = OB_SUCCESS;
is_change = false;
const int64_t MINIMUM_LIMIT = 64 * 1024 * 1024; // at lease 64M
const int64_t MAXIMUM_LIMIT = 1024 * 1024 * 1024; // 1G maximum
int64_t mem_limit = config_mem_limit_;
if (OB_ISNULL(plan_real_info_manager_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(plan_real_info_manager_), K(ret));
} else if (plan_real_info_manager_->get_tenant_id() > OB_SYS_TENANT_ID &&
plan_real_info_manager_->get_tenant_id() <= OB_MAX_RESERVED_TENANT_ID) {
// 50x租户在没有对应的tenant schema,查询配置一定失败
} else if (OB_FAIL(ObPlanRealInfoMgr::get_mem_limit(plan_real_info_manager_->get_tenant_id(),
mem_limit))) {
LOG_WARN("failed to get mem limit", K(ret));
// if memory limit is not retrivable
// overwrite error code, set mem config to default value
// so that total memory use of plan real info can be limited
ret = OB_SUCCESS;
mem_limit = MAXIMUM_LIMIT;
}
if (config_mem_limit_ != mem_limit) {
LOG_TRACE("before change config mem", K(config_mem_limit_));
if (mem_limit < MINIMUM_LIMIT) {
if (lib::is_mini_mode()) {
// do nothing
} else {
config_mem_limit_ = MINIMUM_LIMIT;
}
} else {
config_mem_limit_ = mem_limit;
}
is_change = true;
LOG_TRACE("after change config mem", K(config_mem_limit_));
}
return ret;
}
//剩余内存淘汰曲线图,当mem_limit在[64M, 100M]时, 内存剩余20M时淘汰;
// 当mem_limit在[100M, 5G]时, 内存甚于mem_limit*0.2时淘汰;
// 当mem_limit在[5G, +∞]时, 内存剩余1G时淘汰;
//高低水位线内存差曲线图,当mem_limit在[64M, 100M]时, 内存差为:20M;
// 当mem_limit在[100M, 5G]时,内存差:mem_limit*0.2;
// 当mem_limit在[5G, +∞]时, 内存差是:1G,
// ______
// /
// _____/
// 100M 5G
int ObPlanRealInfoEliminateTask::calc_evict_mem_level(int64_t &low, int64_t &high)
{
int ret = OB_SUCCESS;
const double HIGH_LEVEL_PRECENT = 0.80;
const double LOW_LEVEL_PRECENT = 0.60;
const double HALF_PRECENT = 0.50;
const int64_t BIG_MEMORY_LIMIT = 5368709120; //5G
const int64_t SMALL_MEMORY_LIMIT = 100*1024*1024; //100M
const int64_t LOW_CONFIG = 64*1024*1024; //64M
if (OB_ISNULL(plan_real_info_manager_) || config_mem_limit_ < 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(plan_real_info_manager_), K(config_mem_limit_), K(ret));
} else {
if (config_mem_limit_ > BIG_MEMORY_LIMIT) {
// mem_limit > 5G
high = config_mem_limit_ - static_cast<int64_t>(BIG_MEMORY_LIMIT * (1.0 - HIGH_LEVEL_PRECENT));
low = config_mem_limit_ - static_cast<int64_t>(BIG_MEMORY_LIMIT * (1.0 - LOW_LEVEL_PRECENT)) ;
} else if (config_mem_limit_ >= LOW_CONFIG && config_mem_limit_ < SMALL_MEMORY_LIMIT) {
// 64M =< mem_limit < 100M
high = config_mem_limit_ - static_cast<int64_t>(SMALL_MEMORY_LIMIT * (1.0 - HIGH_LEVEL_PRECENT));
low = config_mem_limit_ - static_cast<int64_t>(SMALL_MEMORY_LIMIT * (1.0 - LOW_LEVEL_PRECENT));
} else if (config_mem_limit_ < LOW_CONFIG) {
//mem_limit < 64M
high = static_cast<int64_t>(static_cast<double>(config_mem_limit_) * HALF_PRECENT);
low = 0;
} else {
high = static_cast<int64_t>(static_cast<double>(config_mem_limit_) * HIGH_LEVEL_PRECENT);
low = static_cast<int64_t>(static_cast<double>(config_mem_limit_) * LOW_LEVEL_PRECENT);
}
}
return ret;
}
void ObPlanRealInfoEliminateTask::runTimerTask()
{
int ret = OB_SUCCESS;
ObConcurrentFIFOAllocator *allocator = NULL;
int64_t evict_high_level = 0;
int64_t evict_low_level = 0;
bool is_change = false;
if (OB_ISNULL(plan_real_info_manager_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(plan_real_info_manager_), K(ret));
} else if (OB_FAIL(check_config_mem_limit(is_change))) {
LOG_WARN("fail to check mem limit stat", K(ret));
} else if (OB_FAIL(calc_evict_mem_level(evict_low_level, evict_high_level))) {
LOG_WARN("fail to get plan real info evict memory level", K(ret));
} else if (OB_ISNULL(allocator = plan_real_info_manager_->get_allocator())) {
ret = OB_NOT_INIT;
LOG_WARN("fail to get plan real info evict memory level", K(ret));
}
if (OB_SUCC(ret)) {
int64_t start_time = ObTimeUtility::current_time();
int64_t evict_batch_count = 0;
//按内存淘汰
if (evict_high_level < allocator->allocated()) {
LOG_INFO("plan real info evict mem start",
K(evict_low_level),
K(evict_high_level),
"size_used",plan_real_info_manager_->get_size_used(),
"mem_used", allocator->allocated());
int64_t last_time_allocated = allocator->allocated();
while (evict_low_level < allocator->allocated()) {
plan_real_info_manager_->release_old();
evict_batch_count++;
if ((evict_low_level < allocator->allocated()) &&
(last_time_allocated == allocator->allocated())) {
LOG_INFO("release old cannot free more memory");
break;
}
last_time_allocated = allocator->allocated();
}
}
//按sql plan记录数淘汰
int64_t high_level_evict_size = ObPlanRealInfoMgr::HIGH_LEVEL_EVICT_SIZE;
int64_t low_level_evict_size = ObPlanRealInfoMgr::LOW_LEVEL_EVICT_SIZE;
if (lib::is_mini_mode()) {
high_level_evict_size = ObPlanRealInfoMgr::MINI_MODE_HIGH_LEVEL_EVICT_SIZE;
low_level_evict_size = ObPlanRealInfoMgr::MINI_MODE_LOW_LEVEL_EVICT_SIZE;
}
if (plan_real_info_manager_->get_size_used() > high_level_evict_size) {
evict_batch_count = (plan_real_info_manager_->get_size_used() - low_level_evict_size)
/ ObPlanRealInfoMgr::BATCH_RELEASE_COUNT;
LOG_INFO("plan real info evict record start",
"size_used",plan_real_info_manager_->get_size_used(),
"mem_used", allocator->allocated());
for (int i = 0; i < evict_batch_count; i++) {
plan_real_info_manager_->release_old();
}
}
//如果sql_plan_memory_limit改变, 则需要将ObConcurrentFIFOAllocator中total_limit_更新;
if (true == is_change) {
allocator->set_total_limit(config_mem_limit_);
}
int64_t end_time = ObTimeUtility::current_time();
LOG_TRACE("plan real info evict task end",
K(evict_high_level),
K(evict_batch_count),
"elapse_time", end_time - start_time,
"size_used",plan_real_info_manager_->get_size_used(),
"mem_used", allocator->allocated());
}
return plan_id_increment_;
}
} // end of namespace sql

View File

@ -55,47 +55,13 @@ struct ObPlanRealInfoRecord
common::ObConcurrentFIFOAllocator *allocator_;
};
class ObPlanRealInfoMgr;
class ObPlanRealInfoEliminateTask : public common::ObTimerTask
{
public:
ObPlanRealInfoEliminateTask();
virtual ~ObPlanRealInfoEliminateTask();
void runTimerTask();
int init(const ObPlanRealInfoMgr *plan_real_info_manager);
int check_config_mem_limit(bool &is_change);
int calc_evict_mem_level(int64_t &low, int64_t &high);
private:
ObPlanRealInfoMgr *plan_real_info_manager_;
int64_t config_mem_limit_;
};
class ObPlanRealInfoMgr
{
public:
static const int64_t SQL_PLAN_PAGE_SIZE = (1LL << 17); // 128K
//进行一次release_old操作删除的记录数
static const int32_t BATCH_RELEASE_COUNT = 5000;
static const int32_t MAX_RELEASE_TIME = 5 * 1000; //5ms
static const int64_t US_PER_HOUR = 3600000000;
//初始化queue大小为1000w
static const int64_t MAX_QUEUE_SIZE = 1000000; //100w
static const int64_t MINI_MODE_MAX_QUEUE_SIZE = 100000; // 10w
//当sql_plan超过900w行记录时触发淘汰
static const int64_t HIGH_LEVEL_EVICT_SIZE = 900000; //90w
static const int64_t MINI_MODE_HIGH_LEVEL_EVICT_SIZE = 90000; // 9w
//按行淘汰的低水位线
static const int64_t LOW_LEVEL_EVICT_SIZE = 800000; //80w
static const int64_t MINI_MODE_LOW_LEVEL_EVICT_SIZE = 80000; // 8w
//启动淘汰检查的时间间隔
static const int64_t EVICT_INTERVAL = 1000000; //1s
static const int64_t PLAN_TABLE_QUEUE_SIZE = 1000;
typedef common::ObRaQueue::Ref Ref;
public:
ObPlanRealInfoMgr();
ObPlanRealInfoMgr(common::ObConcurrentFIFOAllocator *allocator);
virtual ~ObPlanRealInfoMgr();
int init(uint64_t tenant_id,
const int64_t queue_size);
@ -111,33 +77,160 @@ public:
void free(void *ptr);
int get(const int64_t idx, void *&record, Ref* ref);
int revert(Ref* ref);
int release_old(int64_t limit = BATCH_RELEASE_COUNT);
int64_t release_old(int64_t limit);
void clear_queue();
uint64_t get_tenant_id() const;
int64_t get_start_idx() const;
int64_t get_end_idx() const;
int64_t get_size_used();
int64_t get_size();
int64_t get_capacity();
bool is_valid() const;
static int get_mem_limit(uint64_t tenant_id, int64_t &mem_limit);
static int mtl_init(ObPlanRealInfoMgr* &plan_real_info_mgr);
static void mtl_destroy(ObPlanRealInfoMgr* &plan_real_info_mgr);
private:
DISALLOW_COPY_AND_ASSIGN(ObPlanRealInfoMgr);
private:
common::ObConcurrentFIFOAllocator allocator_;//alloc mem for string buf
ObPlanRealInfoEliminateTask task_;
common::ObConcurrentFIFOAllocator *allocator_;
common::ObRaQueue queue_;
bool destroyed_;
bool inited_;
};
// tenant id of this manager
uint64_t tenant_id_;
int tg_id_;
struct ObSqlPlanItem {
ObSqlPlanItem();
virtual ~ObSqlPlanItem();
void reset();
int64_t get_extra_size() const;
int64_t plan_id_;
char* sql_id_;
int64_t sql_id_len_;
int64_t db_id_;
uint64_t plan_hash_;
int64_t gmt_create_;
char* operation_;
int64_t operation_len_;
char* options_;
int64_t options_len_;
char* object_node_;
int64_t object_node_len_;
int64_t object_id_;
char* object_owner_;
int64_t object_owner_len_;
char* object_name_;
int64_t object_name_len_;
char* object_alias_;
int64_t object_alias_len_;
char* object_type_;
int64_t object_type_len_;
char* optimizer_;
int64_t optimizer_len_;
int id_;
int parent_id_;
int depth_;
int position_;
int search_columns_;
bool is_last_child_;
int64_t cost_;
int64_t cardinality_;
int64_t bytes_;
int64_t rowset_;
char* other_tag_;
int64_t other_tag_len_;
char* partition_start_;
int64_t partition_start_len_;
char* partition_stop_;
int64_t partition_stop_len_;
int64_t partition_id_;
char* other_;
int64_t other_len_;
char* distribution_;
int64_t distribution_len_;
int64_t cpu_cost_;
int64_t io_cost_;
int64_t temp_space_;
char* access_predicates_;
int64_t access_predicates_len_;
char* filter_predicates_;
int64_t filter_predicates_len_;
char* startup_predicates_;
int64_t startup_predicates_len_;
char* projection_;
int64_t projection_len_;
char* special_predicates_;
int64_t special_predicates_len_;
int64_t time_;
char* qblock_name_;
int64_t qblock_name_len_;
char* remarks_;
int64_t remarks_len_;
char* other_xml_;
int64_t other_xml_len_;
TO_STRING_KV(
K_(plan_id)
);
};
struct ObSqlPlanItemRecord
{
ObSqlPlanItemRecord();
virtual ~ObSqlPlanItemRecord();
virtual void destroy();
TO_STRING_KV(
K_(data)
);
ObSqlPlanItem data_;
common::ObConcurrentFIFOAllocator *allocator_;
};
class ObPlanItemMgr
{
public:
typedef common::ObRaQueue::Ref Ref;
public:
ObPlanItemMgr(common::ObConcurrentFIFOAllocator *allocator);
virtual ~ObPlanItemMgr();
int init(uint64_t tenant_id,
const int64_t queue_size);
void destroy();
int handle_plan_item(const ObSqlPlanItem &plan_item);
int get_plan(int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan);
int get_plan(const ObString &sql_id,
int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan);
int get_plan_by_hash(const ObString &sql_id,
uint64_t plan_hash,
ObIArray<ObSqlPlanItem*> &plan);
common::ObConcurrentFIFOAllocator *get_allocator();
void* alloc(const int64_t size);
void free(void *ptr);
int get(const int64_t idx, void *&record, Ref* ref);
int revert(Ref* ref);
int64_t release_old(int64_t limit);
void clear_queue();
int64_t get_start_idx() const;
int64_t get_end_idx() const;
int64_t get_size_used();
int64_t get_capacity();
int64_t get_next_plan_id();
int64_t get_last_plan_id();
bool is_valid() const;
TO_STRING_KV(
K_(plan_id_increment)
);
private:
DISALLOW_COPY_AND_ASSIGN(ObPlanItemMgr);
private:
common::ObConcurrentFIFOAllocator *allocator_;
common::ObRaQueue queue_;
int64_t plan_id_increment_;
bool destroyed_;
bool inited_;
};
} // end of namespace sql

View File

@ -121,9 +121,18 @@ int ObSqlPlan::store_sql_plan_for_explain(ObLogPlan* plan,
LOG_WARN("failed to get sql plan infos", K(ret));
} else if (OB_FAIL(set_plan_id_for_explain(sql_plan_infos))) {
LOG_WARN("failed to set plan id", K(ret));
}/* else if (OB_FAIL(inner_store_sql_plan(sql_plan_infos, true))) {
LOG_WARN("failed to store sql plan", K(ret));
}*/ else if (OB_FAIL(format_sql_plan(sql_plan_infos,
}
if (OB_SUCC(ret)) {
if (OB_FAIL(inner_store_sql_plan(sql_plan_infos, true))) {
LOG_WARN("failed to store sql plan", K(ret));
}
if (OB_FAIL(ret)) {
LOG_WARN("failed to store sql plan", K(ret));
ret = OB_SUCCESS;
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(format_sql_plan(sql_plan_infos,
type,
option,
dummy_plan_infos,
@ -132,10 +141,7 @@ int ObSqlPlan::store_sql_plan_for_explain(ObLogPlan* plan,
} else if (OB_FAIL(plan_text_to_strings(out_plan_text, plan_strs))) {
LOG_WARN("failed to convert plan text to strings", K(ret));
}
if (OB_FAIL(ret)) {
LOG_WARN("failed to store sql plan", K(ret));
ret = OB_SUCCESS;
}
destroy_buffer(plan_text);
return ret;
}
@ -187,7 +193,7 @@ int ObSqlPlan::get_sql_plan(const ObString &sql_id,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null session info", K(ret));
} else {
ObSqlPlanMgr *mgr = session_info_->get_sql_plan_manager();
ObPlanItemMgr *mgr = session_info_->get_sql_plan_manager();
if (OB_ISNULL(mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null plan manager", K(ret));
@ -219,7 +225,7 @@ int ObSqlPlan::get_sql_plan_by_hash(const ObString &sql_id,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null session info", K(ret));
} else {
ObSqlPlanMgr *mgr = session_info_->get_sql_plan_manager();
ObPlanItemMgr *mgr = session_info_->get_sql_plan_manager();
if (OB_ISNULL(mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null plan manager", K(ret));
@ -249,11 +255,10 @@ int ObSqlPlan::get_last_explain_plan(ExplainType type,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null session info", K(ret));
} else {
ObSqlPlanMgr *mgr = session_info_->get_plan_table_manager();
ObPlanItemMgr *mgr = session_info_->get_plan_table_manager();
int64_t plan_id = 0;
if (OB_ISNULL(mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null plan manager", K(ret));
//do nothing
} else if (OB_FAIL(mgr->get_plan(mgr->get_last_plan_id(),
sql_plan_infos))) {
LOG_WARN("failed to get sql plan", K(ret));
@ -313,12 +318,11 @@ int ObSqlPlan::set_plan_id_for_explain(ObIArray<ObSqlPlanItem*> &sql_plan_infos)
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null session info", K(ret));
} else {
ObSqlPlanMgr *mgr = session_info_->get_plan_table_manager();
ObPlanItemMgr *mgr = session_info_->get_plan_table_manager();
int64_t timestamp = common::ObTimeUtility::current_time();
int64_t plan_id = 0;
if (OB_ISNULL(mgr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null plan manager", K(ret));
//do nothing
} else {
plan_id = mgr->get_next_plan_id();
}
@ -347,7 +351,7 @@ int ObSqlPlan::set_plan_id_for_excute(ObIArray<ObSqlPlanItem*> &sql_plan_infos,
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null session info", K(ret));
} else {
ObSqlPlanMgr *mgr = session_info_->get_sql_plan_manager();
ObPlanItemMgr *mgr = session_info_->get_sql_plan_manager();
int64_t timestamp = common::ObTimeUtility::current_time();
if (OB_ISNULL(mgr)) {
ret = OB_ERR_UNEXPECTED;
@ -849,23 +853,26 @@ int ObSqlPlan::inner_store_sql_plan(ObIArray<ObSqlPlanItem*> &sql_plan_infos, bo
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null session info", K(ret));
} else {
ObSqlPlanMgr *mgr = NULL;
ObPlanItemMgr *mgr = NULL;
if (for_explain) {
mgr = session_info_->get_plan_table_manager();
} else {
mgr = session_info_->get_sql_plan_manager();
}
if (OB_ISNULL(mgr)) {
if (OB_ISNULL(mgr) && !for_explain) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null plan manager", K(ret));
}
for (int64_t i = 0; OB_SUCC(ret) && i < sql_plan_infos.count(); ++i) {
ObSqlPlanItem *plan_item = sql_plan_infos.at(i);
if (OB_ISNULL(plan_item)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null plan item", K(ret));
} else if (OB_FAIL(mgr->handle_plan_item(*plan_item))) {
LOG_WARN("failed to handle plan item", K(ret));
} else if (OB_ISNULL(mgr) && for_explain) {
//do nothing
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < sql_plan_infos.count(); ++i) {
ObSqlPlanItem *plan_item = sql_plan_infos.at(i);
if (OB_ISNULL(plan_item)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect null plan item", K(ret));
} else if (OB_FAIL(mgr->handle_plan_item(*plan_item))) {
LOG_WARN("failed to handle plan item", K(ret));
}
}
}
}

View File

@ -21,132 +21,13 @@ namespace oceanbase
namespace sql
{
ObSqlPlanItem::ObSqlPlanItem()
{
reset();
}
ObSqlPlanItem::~ObSqlPlanItem()
{
}
void ObSqlPlanItem::reset()
{
plan_id_ = 0;
db_id_ = 0;
sql_id_ = NULL;
sql_id_len_ = 0;
plan_hash_ = 0;
gmt_create_ = 0;
operation_ = NULL;
operation_len_ = 0;
options_ = NULL;
options_len_ = 0;
object_node_ = NULL;
object_node_len_ = 0;
object_id_ = 0;
object_owner_ = NULL;
object_owner_len_ = 0;
object_name_ = NULL;
object_name_len_ = 0;
object_alias_ = NULL;
object_alias_len_ = 0;
object_type_ = NULL;
object_type_len_ = 0;
optimizer_ = NULL;
optimizer_len_ = 0;
id_ = 0;
parent_id_ = 0;
depth_ = 0;
position_ = 0;
is_last_child_ = false;
search_columns_ = 0;
cost_ = 0;
cardinality_ = 0;
bytes_ = 0;
rowset_ = 1;
other_tag_ = NULL;
other_tag_len_ = 0;
partition_start_ = NULL;
partition_start_len_ = 0;
partition_stop_ = NULL;
partition_stop_len_ = 0;
partition_id_ = 0;
other_ = NULL;
other_len_ = 0;
distribution_ = NULL;
distribution_len_ = 0;
cpu_cost_ = 0;
io_cost_ = 0;
temp_space_ = 0;
access_predicates_ = NULL;
access_predicates_len_ = 0;
filter_predicates_ = NULL;
filter_predicates_len_ = 0;
startup_predicates_ = NULL;
startup_predicates_len_ = 0;
projection_ = NULL;
projection_len_ = 0;
special_predicates_ = NULL;
special_predicates_len_ = 0;
time_ = 0;
qblock_name_ = NULL;
qblock_name_len_ = 0;
remarks_ = NULL;
remarks_len_ = 0;
other_xml_ = NULL;
other_xml_len_ = 0;
}
int64_t ObSqlPlanItem::get_extra_size() const
{
return sql_id_len_ +
operation_len_ +
options_len_ +
object_node_len_ +
object_owner_len_ +
object_name_len_ +
object_alias_len_ +
object_type_len_ +
optimizer_len_ +
other_tag_len_ +
partition_start_len_ +
partition_stop_len_ +
other_len_ +
distribution_len_ +
access_predicates_len_ +
filter_predicates_len_ +
startup_predicates_len_ +
projection_len_ +
special_predicates_len_ +
qblock_name_len_ +
remarks_len_ +
other_xml_len_;
}
ObSqlPlanItemRecord::ObSqlPlanItemRecord()
:allocator_(NULL)
{
}
ObSqlPlanItemRecord::~ObSqlPlanItemRecord()
{
destroy();
}
void ObSqlPlanItemRecord::destroy()
{
if (NULL != allocator_) {
allocator_->free(this);
}
}
ObSqlPlanMgr::ObSqlPlanMgr()
:allocator_(),
task_(),
queue_(),
plan_id_increment_(0),
plan_table_mgrs_(),
plan_item_mgr_(nullptr),
plan_real_info_mgr_(nullptr),
destroyed_(false),
inited_(false),
tenant_id_(OB_INVALID_TENANT_ID),
@ -161,37 +42,44 @@ ObSqlPlanMgr::~ObSqlPlanMgr()
}
}
int ObSqlPlanMgr::init(uint64_t tenant_id,
const int64_t queue_size)
int ObSqlPlanMgr::init(uint64_t tenant_id)
{
int ret = OB_SUCCESS;
void *buf = NULL;
tenant_id_ = tenant_id;
int64_t queue_size = lib::is_mini_mode() ?
MINI_MODE_MAX_QUEUE_SIZE : MAX_QUEUE_SIZE;
if (inited_) {
ret = OB_INIT_TWICE;
} else if (OB_FAIL(queue_.init(ObModIds::OB_SQL_PLAN,
queue_size,
tenant_id))) {
SERVER_LOG(WARN, "Failed to init ObMySQLRequestQueue", K(ret));
} else if (OB_FAIL(TG_CREATE_TENANT(lib::TGDefIDs::ReqMemEvict,
tg_id_))) {
SERVER_LOG(WARN, "create failed", K(ret));
} else if (OB_FAIL(TG_START(tg_id_))) {
SERVER_LOG(WARN, "init timer fail", K(ret));
} else if (OB_FAIL(allocator_.init(SQL_PLAN_PAGE_SIZE,
ObModIds::OB_SQL_PLAN,
tenant_id,
INT64_MAX))) {
SERVER_LOG(WARN, "failed to init allocator", K(ret));
} else if (OB_ISNULL(buf=alloc(sizeof(ObPlanItemMgr)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc memory for ObPlanItemMgr", K(ret));
} else if (OB_FALSE_IT(plan_item_mgr_=new(buf)ObPlanItemMgr(get_allocator()))) {
} else if (OB_FAIL(plan_item_mgr_->init(tenant_id, queue_size))) {
LOG_WARN("failed to init plan item manager", K(ret));
} else if (OB_ISNULL(buf=alloc(sizeof(ObPlanRealInfoMgr)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc memory for ObPlanRealInfoMgr", K(ret));
} else if (OB_FALSE_IT(plan_real_info_mgr_=new(buf)ObPlanRealInfoMgr(get_allocator()))) {
} else if (OB_FAIL(plan_real_info_mgr_->init(tenant_id, queue_size))) {
LOG_WARN("failed to init plan real info manager", K(ret));
} else if (OB_FAIL(TG_CREATE_TENANT(lib::TGDefIDs::ReqMemEvict,
tg_id_))) {
SERVER_LOG(WARN, "create failed", K(ret));
} else if (OB_FAIL(TG_START(tg_id_))) {
SERVER_LOG(WARN, "init timer fail", K(ret));
} else if (OB_FAIL(task_.init(this))) {
SERVER_LOG(WARN, "fail to init sql plan timer task", K(ret));
} else if (OB_FAIL(TG_SCHEDULE(tg_id_, task_, EVICT_INTERVAL, true))) {
SERVER_LOG(WARN, "start eliminate task failed", K(ret));
} else {
//check FIFO mem used and sql plan every 1 seconds
if (OB_FAIL(task_.init(this))) {
SERVER_LOG(WARN, "fail to init sql plan timer task", K(ret));
} else if (OB_FAIL(TG_SCHEDULE(tg_id_, task_, EVICT_INTERVAL, true))) {
SERVER_LOG(WARN, "start eliminate task failed", K(ret));
} else {
tenant_id_ = tenant_id;
inited_ = true;
destroyed_ = false;
}
inited_ = true;
destroyed_ = false;
}
if ((OB_FAIL(ret)) && (!inited_)) {
destroy();
@ -203,178 +91,26 @@ void ObSqlPlanMgr::destroy()
{
if (!destroyed_) {
TG_DESTROY(tg_id_);
clear_queue();
queue_.destroy();
if (plan_real_info_mgr_ != NULL) {
plan_real_info_mgr_->destroy();
free(plan_real_info_mgr_);
}
if (plan_item_mgr_ != NULL) {
plan_item_mgr_->destroy();
free(plan_item_mgr_);
}
for (int i = 0; i < plan_table_mgrs_.count(); ++i) {
if (plan_table_mgrs_.at(i) != NULL) {
plan_table_mgrs_.at(i)->destroy();
free(plan_table_mgrs_.at(i));
}
}
allocator_.destroy();
inited_ = false;
destroyed_ = true;
}
}
int ObSqlPlanMgr::handle_plan_item(const ObSqlPlanItem &plan_item)
{
int ret = OB_SUCCESS;
ObSqlPlanItemRecord *record = NULL;
if (!inited_) {
ret = OB_NOT_INIT;
} else {
char *buf = NULL;
//alloc mem from allocator
int64_t pos = sizeof(ObSqlPlanItemRecord);
int64_t total_size = sizeof(ObSqlPlanItemRecord) +
plan_item.get_extra_size();
if (NULL == (buf = (char*)alloc(total_size))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
if (REACH_TIME_INTERVAL(100 * 1000)) {
SERVER_LOG(WARN, "alloc mem failed", K(total_size), K(ret));
}
} else {
record = new(buf)ObSqlPlanItemRecord();
record->allocator_ = &allocator_;
record->data_ = plan_item;
#define DEEP_COPY_DATA(value) \
do { \
if (pos + plan_item.value##len_ > total_size) { \
ret = OB_ERR_UNEXPECTED; \
LOG_WARN("unexpect record size", K(pos), K(plan_item.value##len_), \
K(total_size), K(ret)); \
} else if ((plan_item.value##len_ > 0) && (NULL != plan_item.value)) { \
MEMCPY(buf + pos, plan_item.value, plan_item.value##len_); \
record->data_.value = buf + pos; \
pos += plan_item.value##len_; \
} else { \
record->data_.value = buf + pos; \
} \
} while(0);
DEEP_COPY_DATA(sql_id_);
DEEP_COPY_DATA(operation_);
DEEP_COPY_DATA(options_);
DEEP_COPY_DATA(object_node_);
DEEP_COPY_DATA(object_owner_);
DEEP_COPY_DATA(object_name_);
DEEP_COPY_DATA(object_alias_);
DEEP_COPY_DATA(object_type_);
DEEP_COPY_DATA(optimizer_);
DEEP_COPY_DATA(other_tag_);
DEEP_COPY_DATA(partition_start_);
DEEP_COPY_DATA(partition_stop_);
DEEP_COPY_DATA(other_);
DEEP_COPY_DATA(distribution_);
DEEP_COPY_DATA(access_predicates_);
DEEP_COPY_DATA(filter_predicates_);
DEEP_COPY_DATA(startup_predicates_);
DEEP_COPY_DATA(projection_);
DEEP_COPY_DATA(special_predicates_);
DEEP_COPY_DATA(qblock_name_);
DEEP_COPY_DATA(remarks_);
DEEP_COPY_DATA(other_xml_);
}
//push into queue
if (OB_SUCC(ret)) {
int64_t req_id = 0;
if (OB_FAIL(queue_.push(record, req_id))) {
if (REACH_TIME_INTERVAL(2 * 1000 * 1000)) {
SERVER_LOG(WARN, "push into queue failed", K(ret));
}
free(record);
record = NULL;
}
}
}
return ret;
}
int ObSqlPlanMgr::get_plan(int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan)
{
int ret = OB_SUCCESS;
plan.reuse();
int64_t start_idx = get_start_idx();
int64_t end_idx = get_end_idx();
void *rec = NULL;
Ref ref;
for (int64_t cur_id=start_idx;
(OB_ENTRY_NOT_EXIST == ret || OB_SUCCESS == ret) && cur_id < end_idx;
++cur_id) {
ref.reset();
ret = get(cur_id, rec, &ref);
if (OB_SUCC(ret) && NULL != rec) {
ObSqlPlanItemRecord *record = static_cast<ObSqlPlanItemRecord*>(rec);
if (record->data_.plan_id_ != plan_id) {
//do nothing
} else if (OB_FAIL(plan.push_back(&record->data_))) {
LOG_WARN("failed to push back plan item", K(ret));
}
}
if (ref.idx_ != -1) {
revert(&ref);
}
}
return ret;
}
int ObSqlPlanMgr::get_plan(const ObString &sql_id,
int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan)
{
int ret = OB_SUCCESS;
plan.reuse();
int64_t start_idx = get_start_idx();
int64_t end_idx = get_end_idx();
void *rec = NULL;
Ref ref;
for (int64_t cur_id=start_idx;
(OB_ENTRY_NOT_EXIST == ret || OB_SUCCESS == ret) && cur_id < end_idx;
++cur_id) {
ref.reset();
ret = get(cur_id, rec, &ref);
if (OB_SUCC(ret) && NULL != rec) {
ObSqlPlanItemRecord *record = static_cast<ObSqlPlanItemRecord*>(rec);
if (record->data_.plan_id_ != plan_id ||
sql_id.case_compare(ObString(record->data_.sql_id_len_,record->data_.sql_id_)) != 0) {
//do nothing
} else if (OB_FAIL(plan.push_back(&record->data_))) {
LOG_WARN("failed to push back plan item", K(ret));
}
}
if (ref.idx_ != -1) {
revert(&ref);
}
}
return ret;
}
int ObSqlPlanMgr::get_plan_by_hash(const ObString &sql_id,
uint64_t plan_hash,
ObIArray<ObSqlPlanItem*> &plan)
{
int ret = OB_SUCCESS;
plan.reuse();
int64_t start_idx = get_start_idx();
int64_t end_idx = get_end_idx();
void *rec = NULL;
Ref ref;
for (int64_t cur_id=start_idx;
(OB_ENTRY_NOT_EXIST == ret || OB_SUCCESS == ret) && cur_id < end_idx;
++cur_id) {
ref.reset();
ret = get(cur_id, rec, &ref);
if (OB_SUCC(ret) && NULL != rec) {
ObSqlPlanItemRecord *record = static_cast<ObSqlPlanItemRecord*>(rec);
if (record->data_.plan_hash_ != plan_hash ||
sql_id.case_compare(ObString(record->data_.sql_id_len_,record->data_.sql_id_)) != 0) {
//do nothing
} else if (OB_FAIL(plan.push_back(&record->data_))) {
LOG_WARN("failed to push back plan item", K(ret));
}
}
if (ref.idx_ != -1) {
revert(&ref);
}
}
return ret;
}
ObConcurrentFIFOAllocator *ObSqlPlanMgr::get_allocator()
{
return &allocator_;
@ -392,36 +128,6 @@ void ObSqlPlanMgr::free(void *ptr)
ptr = NULL;
}
int ObSqlPlanMgr::get(const int64_t idx, void *&record, Ref* ref)
{
int ret = OB_SUCCESS;
if (NULL == (record = queue_.get(idx, ref))) {
ret = OB_ENTRY_NOT_EXIST;
}
return ret;
}
int ObSqlPlanMgr::revert(Ref* ref)
{
queue_.revert(ref);
return OB_SUCCESS;
}
int ObSqlPlanMgr::release_old(int64_t limit)
{
void* req = NULL;
int64_t count = 0;
while(count++ < limit && NULL != (req = queue_.pop())) {
free(req);
}
return OB_SUCCESS;
}
void ObSqlPlanMgr::clear_queue()
{
(void)release_old(INT64_MAX);
}
uint64_t ObSqlPlanMgr::get_tenant_id() const
{
return tenant_id_;
@ -432,53 +138,22 @@ bool ObSqlPlanMgr::is_valid() const
return inited_ && !destroyed_;
}
int64_t ObSqlPlanMgr::get_start_idx() const
{
return (int64_t)queue_.get_pop_idx();
}
int64_t ObSqlPlanMgr::get_end_idx() const
{
return (int64_t)queue_.get_push_idx();
}
int64_t ObSqlPlanMgr::get_size_used()
{
return (int64_t)queue_.get_size();
}
int64_t ObSqlPlanMgr::get_capacity()
{
return (int64_t)queue_.get_capacity();
}
int64_t ObSqlPlanMgr::get_next_plan_id()
{
return ++plan_id_increment_;
}
int64_t ObSqlPlanMgr::get_last_plan_id()
{
return plan_id_increment_;
}
int ObSqlPlanMgr::get_mem_limit(uint64_t tenant_id, int64_t &mem_limit)
int ObSqlPlanMgr::get_mem_limit(int64_t &mem_limit)
{
int ret = OB_SUCCESS;
int64_t tenant_mem_limit = lib::get_tenant_memory_limit(tenant_id);
int64_t tenant_mem_limit = lib::get_tenant_memory_limit(tenant_id_);
// default mem limit
mem_limit = static_cast<int64_t>(SQL_PLAN_MEM_FACTOR * tenant_mem_limit);
// get mem_percentage from session info
ObArenaAllocator alloc;
ObObj obj_val;
int64_t mem_pct = 0;
if (OB_FAIL(ObBasicSessionInfo::get_global_sys_variable(tenant_id,
if (OB_FAIL(ObBasicSessionInfo::get_global_sys_variable(tenant_id_,
alloc,
ObDataTypeCastParams(),
ObString(share::OB_SV_SQL_PLAN_MEMORY_PERCENTAGE),
obj_val))) {
LOG_WARN("failed to get global sys variable", K(ret));
LOG_WARN("failed to get global sys variable", K(tenant_id_), K(ret));
} else if (OB_FAIL(obj_val.get_int(mem_pct))) {
LOG_WARN("failed to get int", K(ret), K(obj_val));
} else if (mem_pct < 0 || mem_pct > 100) {
@ -486,30 +161,65 @@ int ObSqlPlanMgr::get_mem_limit(uint64_t tenant_id, int64_t &mem_limit)
LOG_WARN("invalid value of sql plan mem percentage", K(ret), K(mem_pct));
} else {
mem_limit = static_cast<int64_t>(tenant_mem_limit * mem_pct / 100.0);
LOG_DEBUG("tenant sql plan memory limit",
K(tenant_id), K(tenant_mem_limit), K(mem_pct), K(mem_limit));
LOG_DEBUG("tenant sql plan memory limit", K_(tenant_id),
K(tenant_mem_limit), K(mem_pct), K(mem_limit));
}
return ret;
}
int ObSqlPlanMgr::init_plan_manager(uint64_t tenant_id, ObSqlPlanMgr* &sql_plan_mgr)
int ObSqlPlanMgr::init_plan_table_manager(ObPlanItemMgr* &plan_table_mgr)
{
int ret = OB_SUCCESS;
sql_plan_mgr = OB_NEW(ObSqlPlanMgr, ObModIds::OB_SQL_PLAN);
if (nullptr == sql_plan_mgr) {
void *buf = NULL;
plan_table_mgr = NULL;
int64_t evict_high_level = 0;
int64_t evict_low_level = 0;
if (OB_FAIL(task_.calc_evict_mem_level(evict_low_level, evict_high_level))) {
LOG_WARN("fail to get sql plan evict memory level", K(ret));
} else if (evict_high_level <= allocator_.allocated()) {
//do nothing
} else if (OB_ISNULL(buf=alloc(sizeof(ObPlanItemMgr)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc memory for ObSqlPlanMgr", K(ret));
LOG_WARN("failed to alloc memory for ObPlanRealInfoMgr", K(ret));
} else if (OB_FALSE_IT(plan_table_mgr=new(buf)ObPlanItemMgr(get_allocator()))) {
} else if (OB_FAIL(plan_table_mgr->init(tenant_id_, PLAN_TABLE_QUEUE_SIZE))) {
LOG_WARN("failed to init plan real info manager", K(ret));
} else {
int64_t queue_size = PLAN_TABLE_QUEUE_SIZE;
if (OB_FAIL(sql_plan_mgr->init(tenant_id,
queue_size))) {
LOG_WARN("failed to init request manager", K(ret));
ObLockGuard<ObSpinLock> guard(plan_table_mgr_lock_);
if (OB_FAIL(plan_table_mgrs_.push_back(plan_table_mgr))) {
LOG_WARN("failed to push back plan table", K(ret));
}
}
if (OB_FAIL(ret) && sql_plan_mgr != nullptr) {
if (OB_FAIL(ret) && plan_table_mgr != NULL) {
// cleanup
ob_delete(sql_plan_mgr);
sql_plan_mgr = nullptr;
free(plan_table_mgr);
plan_table_mgr = NULL;
}
return ret;
}
int ObSqlPlanMgr::destroy_plan_table_manager(ObPlanItemMgr* &plan_table_mgr)
{
int ret = OB_SUCCESS;
if (plan_table_mgr != NULL) {
bool find = false;
int idx = 0;
ObLockGuard<ObSpinLock> guard(plan_table_mgr_lock_);
for (int i = 0; !find && i < plan_table_mgrs_.count(); ++i) {
if (plan_table_mgrs_.at(i) == plan_table_mgr) {
idx = i;
find = true;
}
}
if (find) {
plan_table_mgrs_.remove(idx);
plan_table_mgr->destroy();
free(plan_table_mgr);
plan_table_mgr = NULL;
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("plan table not in this sql plan mgr", K(ret));
}
}
return ret;
}
@ -517,18 +227,13 @@ int ObSqlPlanMgr::init_plan_manager(uint64_t tenant_id, ObSqlPlanMgr* &sql_plan_
int ObSqlPlanMgr::mtl_init(ObSqlPlanMgr* &sql_plan_mgr)
{
int ret = OB_SUCCESS;
uint64_t tenant_id = lib::current_resource_owner_id();
sql_plan_mgr = OB_NEW(ObSqlPlanMgr, ObModIds::OB_SQL_PLAN);
if (nullptr == sql_plan_mgr) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to alloc memory for ObSqlPlanMgr", K(ret));
} else {
int64_t queue_size = lib::is_mini_mode() ?
MINI_MODE_MAX_QUEUE_SIZE : MAX_QUEUE_SIZE;
uint64_t tenant_id = lib::current_resource_owner_id();
if (OB_FAIL(sql_plan_mgr->init(tenant_id,
queue_size))) {
LOG_WARN("failed to init request manager", K(ret));
}
} else if (OB_FAIL(sql_plan_mgr->init(tenant_id))) {
LOG_WARN("failed to init request manager", K(ret));
}
if (OB_FAIL(ret) && sql_plan_mgr != nullptr) {
// cleanup
@ -588,8 +293,7 @@ int ObSqlPlanEliminateTask::check_config_mem_limit(bool &is_change)
} else if (sql_plan_manager_->get_tenant_id() > OB_SYS_TENANT_ID &&
sql_plan_manager_->get_tenant_id() <= OB_MAX_RESERVED_TENANT_ID) {
// 50x租户在没有对应的tenant schema,查询配置一定失败
} else if (OB_FAIL(ObSqlPlanMgr::get_mem_limit(sql_plan_manager_->get_tenant_id(),
mem_limit))) {
} else if (OB_FAIL(sql_plan_manager_->get_mem_limit(mem_limit))) {
LOG_WARN("failed to get mem limit", K(ret));
// if memory limit is not retrivable
@ -602,7 +306,7 @@ int ObSqlPlanEliminateTask::check_config_mem_limit(bool &is_change)
LOG_TRACE("before change config mem", K(config_mem_limit_));
if (mem_limit < MINIMUM_LIMIT) {
if (lib::is_mini_mode()) {
// do nothing
config_mem_limit_ = mem_limit;
} else {
config_mem_limit_ = MINIMUM_LIMIT;
}
@ -632,8 +336,7 @@ int ObSqlPlanEliminateTask::calc_evict_mem_level(int64_t &low, int64_t &high)
const double LOW_LEVEL_PRECENT = 0.60;
const double HALF_PRECENT = 0.50;
const int64_t BIG_MEMORY_LIMIT = 5368709120; //5G
const int64_t SMALL_MEMORY_LIMIT = 100*1024*1024; //100M
const int64_t LOW_CONFIG = 64*1024*1024; //64M
const int64_t LOW_CONFIG = 10*1024*1024; //10M
if (OB_ISNULL(sql_plan_manager_) || config_mem_limit_ < 0) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(sql_plan_manager_), K(config_mem_limit_), K(ret));
@ -642,17 +345,14 @@ int ObSqlPlanEliminateTask::calc_evict_mem_level(int64_t &low, int64_t &high)
// mem_limit > 5G
high = config_mem_limit_ - static_cast<int64_t>(BIG_MEMORY_LIMIT * (1.0 - HIGH_LEVEL_PRECENT));
low = config_mem_limit_ - static_cast<int64_t>(BIG_MEMORY_LIMIT * (1.0 - LOW_LEVEL_PRECENT)) ;
} else if (config_mem_limit_ >= LOW_CONFIG && config_mem_limit_ < SMALL_MEMORY_LIMIT) {
// 64M =< mem_limit < 100M
high = config_mem_limit_ - static_cast<int64_t>(SMALL_MEMORY_LIMIT * (1.0 - HIGH_LEVEL_PRECENT));
low = config_mem_limit_ - static_cast<int64_t>(SMALL_MEMORY_LIMIT * (1.0 - LOW_LEVEL_PRECENT));
} else if (config_mem_limit_ < LOW_CONFIG) {
//mem_limit < 64M
high = static_cast<int64_t>(static_cast<double>(config_mem_limit_) * HALF_PRECENT);
low = 0;
} else {
} else if (config_mem_limit_ > LOW_CONFIG) {
//mem_limit between 10M and 5G
high = static_cast<int64_t>(static_cast<double>(config_mem_limit_) * HIGH_LEVEL_PRECENT);
low = static_cast<int64_t>(static_cast<double>(config_mem_limit_) * LOW_LEVEL_PRECENT);
} else {
//mem_limit < 10M
high = static_cast<int64_t>(static_cast<double>(config_mem_limit_) * HALF_PRECENT);
low = 0;
}
}
return ret;
@ -665,6 +365,8 @@ void ObSqlPlanEliminateTask::runTimerTask()
int64_t evict_high_level = 0;
int64_t evict_low_level = 0;
bool is_change = false;
int64_t start_time = ObTimeUtility::current_time();
int64_t evict_batch_count = 0;
if (OB_ISNULL(sql_plan_manager_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(sql_plan_manager_), K(ret));
@ -675,56 +377,158 @@ void ObSqlPlanEliminateTask::runTimerTask()
} else if (OB_ISNULL(allocator = sql_plan_manager_->get_allocator())) {
ret = OB_NOT_INIT;
LOG_WARN("fail to get sql plan evict memory level", K(ret));
}
if (OB_SUCC(ret)) {
int64_t start_time = ObTimeUtility::current_time();
int64_t evict_batch_count = 0;
//按内存淘汰
if (evict_high_level < allocator->allocated()) {
LOG_INFO("sql plan evict mem start",
K(evict_low_level),
K(evict_high_level),
"size_used",sql_plan_manager_->get_size_used(),
"mem_used", allocator->allocated());
int64_t last_time_allocated = allocator->allocated();
while (evict_low_level < allocator->allocated()) {
sql_plan_manager_->release_old();
evict_batch_count++;
if ((evict_low_level < allocator->allocated()) &&
(last_time_allocated == allocator->allocated())) {
LOG_INFO("release old cannot free more memory");
break;
}
last_time_allocated = allocator->allocated();
}
}
//按sql plan记录数淘汰
int64_t max_queue_size = sql_plan_manager_->get_capacity();
int64_t high_level_evict_size = max_queue_size * ObSqlPlanMgr::HIGH_LEVEL_EVICT_SIZE_PERCENT;
int64_t low_level_evict_size = max_queue_size * ObSqlPlanMgr::LOW_LEVEL_EVICT_SIZE_PERCENT;
if (sql_plan_manager_->get_size_used() > high_level_evict_size) {
evict_batch_count = (sql_plan_manager_->get_size_used() - low_level_evict_size)
/ ObSqlPlanMgr::BATCH_RELEASE_COUNT;
LOG_INFO("sql plan evict record start",
"size_used",sql_plan_manager_->get_size_used(),
"mem_used", allocator->allocated());
for (int i = 0; i < evict_batch_count; i++) {
sql_plan_manager_->release_old();
}
}
} else if (OB_FAIL(evict_queue_use(evict_batch_count))) {
LOG_WARN("failed to evict queue use", K(ret));
} else if (evict_high_level < allocator->allocated() &&
OB_FAIL(evict_memory_use(evict_low_level,
evict_high_level,
evict_batch_count))) {
LOG_WARN("failed to evict mempry use", K(ret));
} else {
//如果sql_plan_memory_limit改变, 则需要将ObConcurrentFIFOAllocator中total_limit_更新;
if (true == is_change) {
allocator->set_total_limit(config_mem_limit_);
}
int64_t end_time = ObTimeUtility::current_time();
LOG_TRACE("sql plan evict task end",
K(evict_high_level),
K(evict_batch_count),
"elapse_time", end_time - start_time,
"size_used",sql_plan_manager_->get_size_used(),
"mem_used", allocator->allocated());
if (evict_batch_count > 0) {
LOG_INFO("sql plan evict task end",
K(sql_plan_manager_->get_tenant_id()),
K(evict_high_level),
K(evict_low_level),
K(evict_batch_count),
"elapse_time", end_time - start_time,
K_(config_mem_limit),
"mem_used", allocator->allocated());
}
}
}
int ObSqlPlanEliminateTask::evict_memory_use(int64_t evict_low_level,
int64_t evict_high_level,
int64_t &evict_batch_count)
{
int ret = OB_SUCCESS;
ObConcurrentFIFOAllocator *allocator = NULL;
if (OB_ISNULL(sql_plan_manager_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(sql_plan_manager_), K(ret));
} else if (OB_ISNULL(allocator = sql_plan_manager_->get_allocator())) {
ret = OB_NOT_INIT;
LOG_WARN("fail to get sql plan evict memory level", K(ret));
} else {
int64_t evict_count = 0;
//evict plan table mgr
{
ObLockGuard<ObSpinLock> guard(sql_plan_manager_->plan_table_mgr_lock_);
for (int i = 0; i < sql_plan_manager_->get_plan_table_mgrs().count(); ++i) {
if (sql_plan_manager_->get_plan_table_mgrs().at(i) != NULL) {
ObPlanItemMgr *plan_table_mgr = sql_plan_manager_->get_plan_table_mgrs().at(i);
LOG_INFO("plan table evict mem start", K(evict_high_level), "mem_used", allocator->allocated());
while (evict_low_level < allocator->allocated()) {
evict_count = plan_table_mgr->release_old(ObSqlPlanMgr::BATCH_RELEASE_COUNT);
evict_batch_count += evict_count;
if (evict_count < ObSqlPlanMgr::BATCH_RELEASE_COUNT) {
LOG_INFO("release old cannot free more memory");
break;
}
}
}
}
}
//evict plan real info mgr
if (sql_plan_manager_->get_plan_real_info_mgr() != NULL) {
ObPlanRealInfoMgr *plan_real_info_mgr = sql_plan_manager_->get_plan_real_info_mgr();
LOG_INFO("plan real info evict mem start", K(evict_high_level), "mem_used", allocator->allocated());
while (evict_low_level < allocator->allocated()) {
evict_count = plan_real_info_mgr->release_old(ObSqlPlanMgr::BATCH_RELEASE_COUNT);
evict_batch_count += evict_count;
if (evict_count < ObSqlPlanMgr::BATCH_RELEASE_COUNT) {
LOG_INFO("release old cannot free more memory");
break;
}
}
}
//evict plan item mgr
if (sql_plan_manager_->get_plan_item_mgr() != NULL) {
ObPlanItemMgr *plan_item_mgr = sql_plan_manager_->get_plan_item_mgr();
LOG_INFO("plan item evict mem start", K(evict_high_level), "mem_used", allocator->allocated());
while (evict_low_level < allocator->allocated()) {
evict_count = plan_item_mgr->release_old(ObSqlPlanMgr::BATCH_RELEASE_COUNT);
evict_batch_count += evict_count;
if (evict_count < ObSqlPlanMgr::BATCH_RELEASE_COUNT) {
LOG_INFO("release old cannot free more memory");
break;
}
}
}
}
return ret;
}
int ObSqlPlanEliminateTask::evict_queue_use(int64_t &evict_batch_count)
{
int ret = OB_SUCCESS;
ObConcurrentFIFOAllocator *allocator = NULL;
if (OB_ISNULL(sql_plan_manager_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(sql_plan_manager_), K(ret));
} else if (OB_ISNULL(allocator = sql_plan_manager_->get_allocator())) {
ret = OB_NOT_INIT;
LOG_WARN("fail to get sql plan evict memory level", K(ret));
} else {
//evict plan item mgr
if (sql_plan_manager_->get_plan_item_mgr() != NULL) {
ObPlanItemMgr *plan_item_mgr = sql_plan_manager_->get_plan_item_mgr();
int64_t max_queue_size = plan_item_mgr->get_capacity();
int64_t high_level_evict_size = max_queue_size * ObSqlPlanMgr::HIGH_LEVEL_EVICT_SIZE_PERCENT;
int64_t low_level_evict_size = max_queue_size * ObSqlPlanMgr::LOW_LEVEL_EVICT_SIZE_PERCENT;
if (plan_item_mgr->get_size_used() > high_level_evict_size) {
int64_t batch_count = (plan_item_mgr->get_size_used() - low_level_evict_size)
/ ObSqlPlanMgr::BATCH_RELEASE_COUNT;
LOG_INFO("plan item evict record start", "size_used",plan_item_mgr->get_size_used());
for (int i = 0; i < batch_count; i++) {
evict_batch_count += plan_item_mgr->release_old(ObSqlPlanMgr::BATCH_RELEASE_COUNT);
}
}
}
//evict plan real into mgr
if (sql_plan_manager_->get_plan_real_info_mgr() != NULL) {
ObPlanRealInfoMgr *plan_real_info_mgr = sql_plan_manager_->get_plan_real_info_mgr();
int64_t max_queue_size = plan_real_info_mgr->get_capacity();
int64_t high_level_evict_size = max_queue_size * ObSqlPlanMgr::HIGH_LEVEL_EVICT_SIZE_PERCENT;
int64_t low_level_evict_size = max_queue_size * ObSqlPlanMgr::LOW_LEVEL_EVICT_SIZE_PERCENT;
if (plan_real_info_mgr->get_size_used() > high_level_evict_size) {
int64_t batch_count = (plan_real_info_mgr->get_size_used() - low_level_evict_size)
/ ObSqlPlanMgr::BATCH_RELEASE_COUNT;
LOG_INFO("plan real info evict record start", "size_used",plan_real_info_mgr->get_size_used());
for (int i = 0; i < batch_count; i++) {
evict_batch_count += plan_real_info_mgr->release_old(ObSqlPlanMgr::BATCH_RELEASE_COUNT);
}
}
}
//evict plan table mgr
{
ObLockGuard<ObSpinLock> guard(sql_plan_manager_->plan_table_mgr_lock_);
for (int i = 0; i < sql_plan_manager_->get_plan_table_mgrs().count(); ++i) {
if (sql_plan_manager_->get_plan_table_mgrs().at(i) != NULL) {
ObPlanItemMgr *plan_table_mgr = sql_plan_manager_->get_plan_table_mgrs().at(i);
int64_t max_queue_size = plan_table_mgr->get_capacity();
int64_t high_level_evict_size = max_queue_size * ObSqlPlanMgr::HIGH_LEVEL_EVICT_SIZE_PERCENT;
int64_t low_level_evict_size = max_queue_size * ObSqlPlanMgr::LOW_LEVEL_EVICT_SIZE_PERCENT;
if (plan_table_mgr->get_size_used() > high_level_evict_size) {
int64_t batch_count = (plan_table_mgr->get_size_used() - low_level_evict_size)
/ ObSqlPlanMgr::BATCH_RELEASE_COUNT;
LOG_INFO("plan table evict record start", "size_used",plan_table_mgr->get_size_used());
for (int i = 0; i < batch_count; i++) {
evict_batch_count += plan_table_mgr->release_old(ObSqlPlanMgr::BATCH_RELEASE_COUNT);
}
}
}
}
}
}
return ret;
}
} // end of namespace sql
} // end of namespace oceanbase

View File

@ -7,104 +7,13 @@
#define SRC_OBSERVER_SQL_PLAN_MGR_H_
#include "lib/allocator/ob_concurrent_fifo_allocator.h"
#include "observer/mysql/ob_ra_queue.h"
#include "ob_plan_real_info_manager.h"
#include "lib/lock/ob_spin_lock.h"
#include "lib/task/ob_timer.h"
namespace oceanbase
{
namespace sql
{
struct ObSqlPlanItem {
ObSqlPlanItem();
virtual ~ObSqlPlanItem();
void reset();
int64_t get_extra_size() const;
int64_t plan_id_;
char* sql_id_;
int64_t sql_id_len_;
int64_t db_id_;
uint64_t plan_hash_;
int64_t gmt_create_;
char* operation_;
int64_t operation_len_;
char* options_;
int64_t options_len_;
char* object_node_;
int64_t object_node_len_;
int64_t object_id_;
char* object_owner_;
int64_t object_owner_len_;
char* object_name_;
int64_t object_name_len_;
char* object_alias_;
int64_t object_alias_len_;
char* object_type_;
int64_t object_type_len_;
char* optimizer_;
int64_t optimizer_len_;
int id_;
int parent_id_;
int depth_;
int position_;
int search_columns_;
bool is_last_child_;
int64_t cost_;
int64_t cardinality_;
int64_t bytes_;
int64_t rowset_;
char* other_tag_;
int64_t other_tag_len_;
char* partition_start_;
int64_t partition_start_len_;
char* partition_stop_;
int64_t partition_stop_len_;
int64_t partition_id_;
char* other_;
int64_t other_len_;
char* distribution_;
int64_t distribution_len_;
int64_t cpu_cost_;
int64_t io_cost_;
int64_t temp_space_;
char* access_predicates_;
int64_t access_predicates_len_;
char* filter_predicates_;
int64_t filter_predicates_len_;
char* startup_predicates_;
int64_t startup_predicates_len_;
char* projection_;
int64_t projection_len_;
char* special_predicates_;
int64_t special_predicates_len_;
int64_t time_;
char* qblock_name_;
int64_t qblock_name_len_;
char* remarks_;
int64_t remarks_len_;
char* other_xml_;
int64_t other_xml_len_;
TO_STRING_KV(
K_(plan_id)
);
};
struct ObSqlPlanItemRecord
{
ObSqlPlanItemRecord();
virtual ~ObSqlPlanItemRecord();
virtual void destroy();
TO_STRING_KV(
K_(data)
);
ObSqlPlanItem data_;
common::ObConcurrentFIFOAllocator *allocator_;
};
struct ObSqlPlanItemRecords {
void reset() { records_.reuse(); }
ObSEArray<ObSqlPlanItemRecord*, 4> records_;
};
class ObSqlPlanMgr;
class ObSqlPlanEliminateTask : public common::ObTimerTask
{
@ -116,6 +25,10 @@ public:
int init(const ObSqlPlanMgr *sql_plan_manager);
int check_config_mem_limit(bool &is_change);
int calc_evict_mem_level(int64_t &low, int64_t &high);
int evict_memory_use(int64_t evict_low_level,
int64_t evict_high_level,
int64_t &evict_batch_count);
int evict_queue_use(int64_t &evict_batch_count);
private:
ObSqlPlanMgr *sql_plan_manager_;
@ -128,8 +41,6 @@ public:
static const int64_t SQL_PLAN_PAGE_SIZE = (1LL << 17); // 128K
//进行一次release_old操作删除的记录数
static const int32_t BATCH_RELEASE_COUNT = 5000;
static const int32_t MAX_RELEASE_TIME = 5 * 1000; //5ms
static const int64_t US_PER_HOUR = 3600000000;
//初始化queue大小为100w
static const int64_t MAX_QUEUE_SIZE = 1000000; //100w
static const int64_t MINI_MODE_MAX_QUEUE_SIZE = 100000; // 10w
@ -140,54 +51,37 @@ public:
//启动淘汰检查的时间间隔
static const int64_t EVICT_INTERVAL = 1000000; //1s
static const int64_t PLAN_TABLE_QUEUE_SIZE = 100000;
typedef common::ObRaQueue::Ref Ref;
public:
ObSqlPlanMgr();
virtual ~ObSqlPlanMgr();
int init(uint64_t tenant_id,
const int64_t queue_size);
int init(uint64_t tenant_id);
void destroy();
int handle_plan_item(const ObSqlPlanItem &plan_item);
int get_plan(int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan);
int get_plan(const ObString &sql_id,
int64_t plan_id,
ObIArray<ObSqlPlanItem*> &plan);
int get_plan_by_hash(const ObString &sql_id,
uint64_t plan_hash,
ObIArray<ObSqlPlanItem*> &plan);
common::ObConcurrentFIFOAllocator *get_allocator();
void* alloc(const int64_t size);
void free(void *ptr);
int get(const int64_t idx, void *&record, Ref* ref);
int revert(Ref* ref);
int release_old(int64_t limit = BATCH_RELEASE_COUNT);
void clear_queue();
uint64_t get_tenant_id() const;
int64_t get_start_idx() const;
int64_t get_end_idx() const;
int64_t get_size_used();
int64_t get_capacity();
int64_t get_next_plan_id();
int64_t get_last_plan_id();
bool is_valid() const;
inline ObPlanItemMgr *get_plan_item_mgr() { return plan_item_mgr_; }
inline ObPlanRealInfoMgr *get_plan_real_info_mgr() { return plan_real_info_mgr_; }
inline ObIArray<ObPlanItemMgr*> &get_plan_table_mgrs() { return plan_table_mgrs_; }
static int get_mem_limit(uint64_t tenant_id, int64_t &mem_limit);
static int init_plan_manager(uint64_t tenant_id, ObSqlPlanMgr* &sql_plan_mgr);
int get_mem_limit(int64_t &mem_limit);
int init_plan_table_manager(ObPlanItemMgr* &plan_table_mgr);
int destroy_plan_table_manager(ObPlanItemMgr* &plan_table_mgr);
static int mtl_init(ObSqlPlanMgr* &sql_plan_mgr);
static void mtl_destroy(ObSqlPlanMgr* &sql_plan_mgr);
private:
DISALLOW_COPY_AND_ASSIGN(ObSqlPlanMgr);
friend class ObSqlPlanEliminateTask;
private:
common::ObConcurrentFIFOAllocator allocator_;//alloc mem for string buf
common::ObConcurrentFIFOAllocator allocator_;
ObSqlPlanEliminateTask task_;
common::ObRaQueue queue_;
int64_t plan_id_increment_;
ObSEArray<ObPlanItemMgr*, 8> plan_table_mgrs_;
mutable ObSpinLock plan_table_mgr_lock_;
ObPlanItemMgr *plan_item_mgr_;
ObPlanRealInfoMgr *plan_real_info_mgr_;
bool destroyed_;
bool inited_;
@ -196,6 +90,8 @@ private:
int tg_id_;
};
} // end of namespace sql
} // end of namespace oceanbase

View File

@ -235,8 +235,14 @@ int ObSQLSessionInfo::init(uint32_t sessid, uint64_t proxy_sessid,
void ObSQLSessionInfo::destroy_session_plan_mgr()
{
int ret = OB_SUCCESS;
if (NULL != plan_table_manager_) {
ObSqlPlanMgr::mtl_destroy(plan_table_manager_);
MTL_SWITCH(get_priv_tenant_id()) {
ObSqlPlanMgr *sql_plan_mgr = MTL(ObSqlPlanMgr*);
if (sql_plan_mgr != NULL) {
sql_plan_mgr->destroy_plan_table_manager(plan_table_manager_);
}
}
}
}
@ -772,24 +778,30 @@ sql::ObFLTSpanMgr* ObSQLSessionInfo::get_flt_span_manager()
return flt_span_mgr_;
}
ObSqlPlanMgr* ObSQLSessionInfo::get_sql_plan_manager()
ObPlanItemMgr* ObSQLSessionInfo::get_sql_plan_manager()
{
int ret = OB_SUCCESS;
if (NULL == sql_plan_manager_) {
MTL_SWITCH(get_priv_tenant_id()) {
sql_plan_manager_ = MTL(ObSqlPlanMgr*);
ObSqlPlanMgr* sql_plan_mgr = MTL(ObSqlPlanMgr*);
if (sql_plan_mgr != NULL) {
sql_plan_manager_ = sql_plan_mgr->get_plan_item_mgr();
}
}
}
return sql_plan_manager_;
}
ObSqlPlanMgr* ObSQLSessionInfo::get_plan_table_manager()
ObPlanItemMgr* ObSQLSessionInfo::get_plan_table_manager()
{
int ret = OB_SUCCESS;
if (NULL == plan_table_manager_) {
if (OB_FAIL(ObSqlPlanMgr::init_plan_manager(get_effective_tenant_id(),
plan_table_manager_))) {
LOG_WARN("failed to init plan manager", K(ret));
MTL_SWITCH(get_priv_tenant_id()) {
ObSqlPlanMgr* sql_plan_mgr = MTL(ObSqlPlanMgr*);
if (NULL != sql_plan_mgr &&
OB_FAIL(sql_plan_mgr->init_plan_table_manager(plan_table_manager_))) {
LOG_WARN("failed to init plan table manager", K(ret));
}
}
}
return plan_table_manager_;

View File

@ -83,7 +83,7 @@ class ObPsSessionInfo;
class ObPsStmtInfo;
class ObStmt;
class ObSQLSessionInfo;
class ObSqlPlanMgr;
class ObPlanItemMgr;
class SessionInfoKey
{
@ -580,8 +580,8 @@ public:
ObPsCache *get_ps_cache();
obmysql::ObMySQLRequestManager *get_request_manager();
sql::ObFLTSpanMgr *get_flt_span_manager();
ObSqlPlanMgr *get_sql_plan_manager();
ObSqlPlanMgr *get_plan_table_manager();
ObPlanItemMgr *get_sql_plan_manager();
ObPlanItemMgr *get_plan_table_manager();
void set_user_priv_set(const ObPrivSet priv_set) { user_priv_set_ = priv_set; }
void set_db_priv_set(const ObPrivSet priv_set) { db_priv_set_ = priv_set; }
void set_show_warnings_buf(int error_code);
@ -1034,8 +1034,8 @@ private:
char tenant_buff_[sizeof(share::ObTenantSpaceFetcher)];
obmysql::ObMySQLRequestManager *request_manager_;
sql::ObFLTSpanMgr *flt_span_mgr_;
ObSqlPlanMgr *sql_plan_manager_;
ObSqlPlanMgr *plan_table_manager_;
ObPlanItemMgr *sql_plan_manager_;
ObPlanItemMgr *plan_table_manager_;
ObPlanCache *plan_cache_;
ObPsCache *ps_cache_;
//记录select stmt中scan出来的结果集行数,供设置sql_calc_found_row时,found_row()使用;