fixed problems when shrink log disk size

This commit is contained in:
HaHaJeff
2023-07-18 08:18:25 +00:00
committed by ob-robot
parent 4dc8f35b58
commit 928f831487
20 changed files with 494 additions and 391 deletions

View File

@ -171,6 +171,8 @@ public:
} }
return ret; return ret;
} }
int update_server_log_disk(const int64_t log_disk_size)
{return OB_SUCCESS;}
public: public:
int simple_init(const std::string &cluster_name, int simple_init(const std::string &cluster_name,
const common::ObAddr &addr, const common::ObAddr &addr,

View File

@ -1480,5 +1480,15 @@ int ObSimpleLogClusterTestEnv::wait_until_disk_space_to(const int64_t server_id,
return ret; return ret;
} }
int ObSimpleLogClusterTestEnv::update_server_log_disk(const int64_t log_disk_size)
{
int ret = OB_SUCCESS;
auto cluster = get_cluster();
for (auto srv : cluster) {
srv->update_server_log_disk(log_disk_size);
}
return ret;
}
} // end namespace unittest } // end namespace unittest
} // end namespace oceanbase } // end namespace oceanbase

View File

@ -249,6 +249,7 @@ public:
bool is_degraded(const PalfHandleImplGuard &leader, const int64_t degraded_server_idx); bool is_degraded(const PalfHandleImplGuard &leader, const int64_t degraded_server_idx);
bool is_upgraded(PalfHandleImplGuard &leader, const int64_t palf_id); bool is_upgraded(PalfHandleImplGuard &leader, const int64_t palf_id);
int wait_until_disk_space_to(const int64_t server_id, const int64_t expect_log_disk_space); int wait_until_disk_space_to(const int64_t server_id, const int64_t expect_log_disk_space);
int update_server_log_disk(const int64_t log_disk_size);
public: public:
static int64_t palf_id_; static int64_t palf_id_;
private: private:

View File

@ -163,44 +163,10 @@ int ObSimpleLogServer::simple_init(
return ret; return ret;
} }
int ObSimpleLogServer::construct_allowed_new_log_disk_(const uint64_t tenant_id,
const int64_t expected_log_disk_size,
const int64_t old_log_disk_size,
int64_t &allowed_new_log_disk_size)
{
int ret = OB_SUCCESS;
bool can_update_log_disk_size_with_expected_log_disk = true;
int64_t palf_log_disk_size = 0;
MAKE_TENANT_SWITCH_SCOPE_GUARD(guard);
if (OB_FAIL(guard.switch_to(tenant_id))) {
LOG_WARN("failed to switch tenant", K(ret), K(tenant_id));
} else {
ObLogService *log_service = MTL(ObLogService*);
int64_t used_log_disk_size = 0;
if (OB_ISNULL(log_service)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("ObLogService is nullptr", K(ret), KP(log_service));
} else if (OB_FAIL(log_service->get_palf_stable_disk_usage(used_log_disk_size, palf_log_disk_size))) {
LOG_WARN("failed to update_log_disk_size", K(ret), K(palf_log_disk_size), K(allowed_new_log_disk_size), K(expected_log_disk_size));
} else if (FALSE_IT(can_update_log_disk_size_with_expected_log_disk = (expected_log_disk_size >= palf_log_disk_size))) {
// For shrinking log disk, we still update log disk size of 'new_unit' to 'old_log_disk_size'.
} else if (!can_update_log_disk_size_with_expected_log_disk
&& FALSE_IT(allowed_new_log_disk_size = old_log_disk_size)) {
// For expanding log disk, we update log disk size of 'new_unit' to 'expected_log_disk_size'.
} else if (can_update_log_disk_size_with_expected_log_disk
&& FALSE_IT(allowed_new_log_disk_size = expected_log_disk_size)) {
} else {
LOG_INFO("construct_new_log_disk success", K(ret), K(tenant_id), K(can_update_log_disk_size_with_expected_log_disk),
K(old_log_disk_size), K(allowed_new_log_disk_size), K(expected_log_disk_size));
}
}
return ret;
}
int ObSimpleLogServer::update_tenant_log_disk_size_(const uint64_t tenant_id, int ObSimpleLogServer::update_tenant_log_disk_size_(const uint64_t tenant_id,
const int64_t expected_log_disk_size,
const int64_t old_log_disk_size, const int64_t old_log_disk_size,
const int64_t allowed_new_log_disk_size) const int64_t new_log_disk_size,
int64_t &allowed_new_log_disk_size)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
MAKE_TENANT_SWITCH_SCOPE_GUARD(guard); MAKE_TENANT_SWITCH_SCOPE_GUARD(guard);
@ -208,15 +174,15 @@ int ObSimpleLogServer::update_tenant_log_disk_size_(const uint64_t tenant_id,
ObLogService *log_service = MTL(ObLogService *); ObLogService *log_service = MTL(ObLogService *);
if (OB_ISNULL(log_service)) { if (OB_ISNULL(log_service)) {
ret = OB_ERR_UNEXPECTED; ret = OB_ERR_UNEXPECTED;
} else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(expected_log_disk_size))) { } else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(new_log_disk_size))) {
LOG_WARN("failed to update_log_disk_usage_limit_size", K(ret), K(tenant_id), K(expected_log_disk_size), LOG_WARN("failed to update_log_disk_usage_limit_size", K(ret), K(tenant_id), K(new_log_disk_size),
K(old_log_disk_size), K(allowed_new_log_disk_size)); K(old_log_disk_size), K(allowed_new_log_disk_size));
} else if (OB_FAIL(log_block_pool_.update_tenant(old_log_disk_size, allowed_new_log_disk_size))) { } else if (OB_FAIL(log_block_pool_.update_tenant(old_log_disk_size, new_log_disk_size, allowed_new_log_disk_size, log_service))) {
LOG_WARN("failed to update teannt int ObServerLogBlockMGR", K(ret), K(tenant_id), K(expected_log_disk_size), LOG_WARN("failed to update teannt int ObServerLogBlockMGR", K(ret), K(tenant_id), K(new_log_disk_size),
K(old_log_disk_size), K(allowed_new_log_disk_size)); K(old_log_disk_size), K(allowed_new_log_disk_size));
} else { } else {
disk_opts_.log_disk_usage_limit_size_ = allowed_new_log_disk_size; disk_opts_.log_disk_usage_limit_size_ = allowed_new_log_disk_size;
LOG_INFO("update_log_disk_usage_limit_size success", K(ret), K(tenant_id), K(expected_log_disk_size), LOG_INFO("update_log_disk_usage_limit_size success", K(ret), K(tenant_id), K(new_log_disk_size),
K(old_log_disk_size), K(allowed_new_log_disk_size), K(disk_opts_)); K(old_log_disk_size), K(allowed_new_log_disk_size), K(disk_opts_));
} }
} }
@ -226,26 +192,26 @@ int ObSimpleLogServer::update_tenant_log_disk_size_(const uint64_t tenant_id,
int ObSimpleLogServer::update_disk_opts_no_lock_(const PalfDiskOptions &opts) int ObSimpleLogServer::update_disk_opts_no_lock_(const PalfDiskOptions &opts)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
CLOG_LOG(INFO, "begin update_disk_opts_no_lock_", K(opts), K(disk_opts_), K(inner_table_disk_opts_));
int64_t old_log_disk_size = disk_opts_.log_disk_usage_limit_size_; int64_t old_log_disk_size = disk_opts_.log_disk_usage_limit_size_;
int64_t expected_log_disk_size = opts.log_disk_usage_limit_size_; int64_t new_log_disk_size = opts.log_disk_usage_limit_size_;
int64_t allowed_new_log_disk_size = 0; int64_t allowed_new_log_disk_size = 0;
// 内部表中的disk_opts立马生效 // 内部表中的disk_opts立马生效
inner_table_disk_opts_ = opts; inner_table_disk_opts_ = opts;
// disk_opts_表示本地持久化最新的disk_opts,在construct_allowed_new_log_disk_中会修改disk_opts_的log_disk_usage_limit_size_ // disk_opts_表示本地持久化最新的disk_opts,log_disk_percentage_延迟生效
disk_opts_ = opts; disk_opts_ = opts;
disk_opts_.log_disk_usage_limit_size_ = old_log_disk_size;
if (!opts.is_valid()) { if (!opts.is_valid()) {
ret = OB_INVALID_ARGUMENT; ret = OB_INVALID_ARGUMENT;
CLOG_LOG(WARN, "invalid argument", K(opts)); CLOG_LOG(WARN, "invalid argument", K(opts));
} else if (OB_FAIL(construct_allowed_new_log_disk_(node_id_, expected_log_disk_size, } else if (OB_FAIL(update_tenant_log_disk_size_(node_id_,
old_log_disk_size, allowed_new_log_disk_size))) { old_log_disk_size,
CLOG_LOG(WARN, "construct_allowed_new_log_disk_ failed", K(expected_log_disk_size), K(old_log_disk_size), new_log_disk_size,
K(allowed_new_log_disk_size)); allowed_new_log_disk_size))) {
} else if (OB_FAIL(update_tenant_log_disk_size_(node_id_, expected_log_disk_size, CLOG_LOG(WARN, "update_tenant_log_disk_size_ failed", K(new_log_disk_size), K(old_log_disk_size),
old_log_disk_size, allowed_new_log_disk_size))) {
CLOG_LOG(WARN, "update_tenant_log_disk_size_ failed", K(expected_log_disk_size), K(old_log_disk_size),
K(allowed_new_log_disk_size)); K(allowed_new_log_disk_size));
} else { } else {
CLOG_LOG(INFO, "update_disk_opts success", K(opts), K(disk_opts_), K(expected_log_disk_size), K(old_log_disk_size), CLOG_LOG(INFO, "update_disk_opts success", K(opts), K(disk_opts_), K(new_log_disk_size), K(old_log_disk_size),
K(allowed_new_log_disk_size)); K(allowed_new_log_disk_size));
} }
return ret; return ret;
@ -272,6 +238,12 @@ int ObSimpleLogServer::try_resize()
return ret; return ret;
} }
int ObSimpleLogServer::update_server_log_disk(const int64_t log_disk_size)
{
ObSpinLockGuard guard(log_disk_lock_);
return log_block_pool_.resize_(log_disk_size);
}
int ObSimpleLogServer::init_memory_dump_timer_() int ObSimpleLogServer::init_memory_dump_timer_()
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
@ -349,7 +321,8 @@ int ObSimpleLogServer::init_io_(const std::string &cluster_name)
storage_env.default_block_size_ = OB_DEFAULT_MACRO_BLOCK_SIZE; storage_env.default_block_size_ = OB_DEFAULT_MACRO_BLOCK_SIZE;
storage_env.data_disk_size_ = 1024 * 1024 * 1024; storage_env.data_disk_size_ = 1024 * 1024 * 1024;
storage_env.data_disk_percentage_ = 0; storage_env.data_disk_percentage_ = 0;
storage_env.log_disk_size_ = 10LL * 1024 * 1024 * 1024; // 当disk_opts_有效时,使用disk_opts_中记录的log_disk_usage_limit_size_作为log_block_pool_的初始值,否则重启会失败
storage_env.log_disk_size_ = disk_opts_.is_valid() ? disk_opts_.log_disk_usage_limit_size_ : 2LL * 1024 * 1024 * 1024;
storage_env.log_disk_percentage_ = 0; storage_env.log_disk_percentage_ = 0;
storage_env.log_spec_.log_dir_ = slog_dir.c_str(); storage_env.log_spec_.log_dir_ = slog_dir.c_str();
@ -394,7 +367,7 @@ int ObSimpleLogServer::init_log_service_()
if (disk_opts_.is_valid()) { if (disk_opts_.is_valid()) {
opts.disk_options_ = disk_opts_; opts.disk_options_ = disk_opts_;
} else { } else {
opts.disk_options_.log_disk_usage_limit_size_ = 10 * 1024 * 1024 * 1024ul; opts.disk_options_.log_disk_usage_limit_size_ = 2 * 1024 * 1024 * 1024ul;
opts.disk_options_.log_disk_utilization_threshold_ = 80; opts.disk_options_.log_disk_utilization_threshold_ = 80;
opts.disk_options_.log_disk_utilization_limit_threshold_ = 95; opts.disk_options_.log_disk_utilization_limit_threshold_ = 95;
opts.disk_options_.log_disk_throttling_percentage_ = 100; opts.disk_options_.log_disk_throttling_percentage_ = 100;

View File

@ -251,6 +251,7 @@ public:
virtual int create_mock_election(const int64_t palf_id, MockElection *&mock_election) = 0; virtual int create_mock_election(const int64_t palf_id, MockElection *&mock_election) = 0;
virtual int remove_mock_election(const int64_t palf_id) = 0; virtual int remove_mock_election(const int64_t palf_id) = 0;
virtual int set_leader(const int64_t palf_id, const common::ObAddr &leader, const int64_t new_epoch = 0) = 0; virtual int set_leader(const int64_t palf_id, const common::ObAddr &leader, const int64_t new_epoch = 0) = 0;
virtual int update_server_log_disk(const int64_t log_disk_size) = 0;
DECLARE_PURE_VIRTUAL_TO_STRING; DECLARE_PURE_VIRTUAL_TO_STRING;
}; };
@ -287,6 +288,7 @@ public:
virtual int update_disk_opts(const PalfDiskOptions &opts) override final; virtual int update_disk_opts(const PalfDiskOptions &opts) override final;
virtual int get_disk_opts(PalfDiskOptions &opts) override final virtual int get_disk_opts(PalfDiskOptions &opts) override final
{ {
ObSpinLockGuard guard(log_disk_lock_);
opts = disk_opts_; opts = disk_opts_;
return OB_SUCCESS; return OB_SUCCESS;
} }
@ -368,6 +370,7 @@ public:
} }
return ret; return ret;
} }
int update_server_log_disk(const int64_t log_disk_size);
TO_STRING_KV(K_(node_id), K_(addr), KP(palf_env_)); TO_STRING_KV(K_(node_id), K_(addr), KP(palf_env_));
protected: protected:
@ -375,15 +378,10 @@ protected:
int init_network_(const common::ObAddr &addr, const bool is_bootstrap); int init_network_(const common::ObAddr &addr, const bool is_bootstrap);
int init_log_service_(); int init_log_service_();
int init_memory_dump_timer_(); int init_memory_dump_timer_();
// 更新log_disk_size的逻辑保持和ObMultiTenant.cpp中维护同名函数一样
int construct_allowed_new_log_disk_(const uint64_t tenant_id,
const int64_t expected_log_disk_size,
const int64_t old_log_disk_size,
int64_t &allowed_new_log_disk_size);
int update_tenant_log_disk_size_(const uint64_t tenant_id, int update_tenant_log_disk_size_(const uint64_t tenant_id,
const int64_t expected_log_disk_size,
const int64_t old_log_disk_size, const int64_t old_log_disk_size,
const int64_t allowed_log_disk_size); const int64_t new_log_disk_size,
int64_t &allowed_log_disk_size);
int update_disk_opts_no_lock_(const PalfDiskOptions &opts); int update_disk_opts_no_lock_(const PalfDiskOptions &opts);
private: private:
@ -415,8 +413,11 @@ private:
ObSrvRpcProxy srv_proxy_; ObSrvRpcProxy srv_proxy_;
logservice::coordinator::ObFailureDetector detector_; logservice::coordinator::ObFailureDetector detector_;
MockElectionMap mock_election_map_; MockElectionMap mock_election_map_;
// ObTenantUnit以及__all_unit_configs
ObSpinLock log_disk_lock_; ObSpinLock log_disk_lock_;
// 本地已生效日志盘规格
palf::PalfDiskOptions disk_opts_; palf::PalfDiskOptions disk_opts_;
// 内部表中记录日志盘规格
palf::PalfDiskOptions inner_table_disk_opts_; palf::PalfDiskOptions inner_table_disk_opts_;
ObLooper looper_; ObLooper looper_;
}; };

View File

@ -66,6 +66,8 @@ bool ObSimpleLogClusterTestBase::need_add_arb_server_ = false;
TEST_F(TestObSimpleLogDiskMgr, out_of_disk_space) TEST_F(TestObSimpleLogDiskMgr, out_of_disk_space)
{ {
update_server_log_disk(10*1024*1024*1024ul);
update_disk_options(10*1024*1024*1024ul/palf::PALF_PHY_BLOCK_SIZE);
SET_CASE_LOG_FILE(TEST_NAME, "out_of_disk_space"); SET_CASE_LOG_FILE(TEST_NAME, "out_of_disk_space");
int64_t id = ATOMIC_AAF(&palf_id_, 1); int64_t id = ATOMIC_AAF(&palf_id_, 1);
int server_idx = 0; int server_idx = 0;
@ -117,7 +119,8 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_basic)
palf_env->palf_env_impl_.disk_options_wrapper_.status_); palf_env->palf_env_impl_.disk_options_wrapper_.status_);
EXPECT_EQ(palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_.log_disk_usage_limit_size_, EXPECT_EQ(palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_recycling_blocks_.log_disk_usage_limit_size_,
20*PALF_PHY_BLOCK_SIZE); 20*PALF_PHY_BLOCK_SIZE);
// 可以在上一次为缩容完成之前,可以继续缩容
// case1: 在上一次未缩容完成之前,可以继续缩容
EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 10)); EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 10));
usleep(1000*1000+palf::BlockGCTimerTask::BLOCK_GC_TIMER_INTERVAL_MS); usleep(1000*1000+palf::BlockGCTimerTask::BLOCK_GC_TIMER_INTERVAL_MS);
EXPECT_EQ(PalfDiskOptionsWrapper::Status::SHRINKING_STATUS, EXPECT_EQ(PalfDiskOptionsWrapper::Status::SHRINKING_STATUS,
@ -130,8 +133,7 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_basic)
EXPECT_EQ(OB_SUCCESS, get_disk_options(leader_idx, opts)); EXPECT_EQ(OB_SUCCESS, get_disk_options(leader_idx, opts));
EXPECT_EQ(opts.log_disk_usage_limit_size_, 10*1024*1024*1024ul); EXPECT_EQ(opts.log_disk_usage_limit_size_, 10*1024*1024*1024ul);
} }
// 可以在上一次未缩容完成之前,可以继续扩容, 同时由于扩容后日志盘依旧小于第一次缩容 // case2: 在上一次未缩容完成之前,可以继续扩容, 同时由于扩容后日志盘依旧小于第一次缩容,因此依旧处于缩容状态.
// ,因此依旧处于缩容状态.
EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 11)); EXPECT_EQ(OB_SUCCESS, update_disk_options(leader_idx, 11));
usleep(1000*1000+palf::BlockGCTimerTask::BLOCK_GC_TIMER_INTERVAL_MS); usleep(1000*1000+palf::BlockGCTimerTask::BLOCK_GC_TIMER_INTERVAL_MS);
EXPECT_EQ(PalfDiskOptionsWrapper::Status::SHRINKING_STATUS, EXPECT_EQ(PalfDiskOptionsWrapper::Status::SHRINKING_STATUS,
@ -171,6 +173,37 @@ TEST_F(TestObSimpleLogDiskMgr, update_disk_options_basic)
} }
} }
TEST_F(TestObSimpleLogDiskMgr, shrink_log_disk)
{
SET_CASE_LOG_FILE(TEST_NAME, "shrink_log_disk");
OB_LOGGER.set_log_level("INFO");
// 验证缩容由于单日志流最少需要512MB日志盘失败
// 保证能同时容纳两个日志流
PalfEnv *palf_env = NULL;
int64_t leader_idx = 0;
PalfHandleImplGuard leader;
share::SCN create_scn = share::SCN::base_scn();
int server_idx = 0;
EXPECT_EQ(OB_SUCCESS, get_palf_env(server_idx, palf_env));
EXPECT_EQ(OB_SUCCESS, update_disk_options(16));
EXPECT_EQ(PalfDiskOptionsWrapper::Status::NORMAL_STATUS,
palf_env->palf_env_impl_.disk_options_wrapper_.status_);
EXPECT_EQ(palf_env->palf_env_impl_.disk_options_wrapper_.disk_opts_for_stopping_writing_.log_disk_usage_limit_size_,
16*PALF_PHY_BLOCK_SIZE);
int64_t tmp_id1 = ATOMIC_AAF(&palf_id_, 1);
{
PalfHandleImplGuard leader;
EXPECT_EQ(OB_SUCCESS, create_paxos_group(tmp_id1, leader_idx, leader));
}
int64_t tmp_id2 = ATOMIC_AAF(&palf_id_, 1);
{
PalfHandleImplGuard leader;
EXPECT_EQ(OB_SUCCESS, create_paxos_group(tmp_id2, leader_idx, leader));
}
EXPECT_EQ(OB_NOT_SUPPORTED, update_disk_options(9));
EXPECT_EQ(OB_SUCCESS, delete_paxos_group(tmp_id1));
}
TEST_F(TestObSimpleLogDiskMgr, update_disk_options_restart) TEST_F(TestObSimpleLogDiskMgr, update_disk_options_restart)
{ {
disable_hot_cache_ = true; disable_hot_cache_ = true;

View File

@ -457,7 +457,8 @@ public:
TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func) TEST_F(TestObSimpleLogClusterLogEngine, io_reducer_basic_func)
{ {
SET_CASE_LOG_FILE(TEST_NAME, "io_reducer_func"); SET_CASE_LOG_FILE(TEST_NAME, "io_reducer_func");
update_server_log_disk(4*1024*1024*1024ul);
update_disk_options(4*1024*1024*1024ul/palf::PALF_PHY_BLOCK_SIZE);
OB_LOGGER.set_log_level("TRACE"); OB_LOGGER.set_log_level("TRACE");
PALF_LOG(INFO, "begin io_reducer_basic_func"); PALF_LOG(INFO, "begin io_reducer_basic_func");
PalfHandleImplGuard leader_1; PalfHandleImplGuard leader_1;

View File

@ -182,14 +182,14 @@ TEST_F(TestObSimpleLogClusterRebuild, test_old_leader_rebuild)
EXPECT_EQ(OB_SUCCESS, get_leader(id, new_leader, new_leader_idx)); EXPECT_EQ(OB_SUCCESS, get_leader(id, new_leader, new_leader_idx));
PALF_LOG(INFO, "after get_leader", K(id), K(leader_idx), K(new_leader_idx)); PALF_LOG(INFO, "after get_leader", K(id), K(leader_idx), K(new_leader_idx));
// submit logs // submit logs
EXPECT_EQ(OB_SUCCESS, submit_log(new_leader, 64 * 6, id, MB)); EXPECT_EQ(OB_SUCCESS, submit_log(new_leader, 64 * 8, id, MB));
// update new_leader's disk option, only reserves 4 * 80% log blocks, // update new_leader's disk option, only reserves 4 * 80% log blocks,
// that means 2 blocks will be recycled // that means 2 blocks will be recycled
PALF_LOG(INFO, "begin advance_base_lsn", K(id), K(leader_idx), K(new_leader_idx)); PALF_LOG(INFO, "begin advance_base_lsn", K(id), K(leader_idx), K(new_leader_idx));
LSN recycle_lsn(2 * PALF_BLOCK_SIZE); LSN recycle_lsn(2 * PALF_BLOCK_SIZE);
EXPECT_EQ(OB_SUCCESS, new_leader.palf_handle_impl_->set_base_lsn(recycle_lsn)); EXPECT_EQ(OB_SUCCESS, new_leader.palf_handle_impl_->set_base_lsn(recycle_lsn));
update_disk_options(new_leader_idx, 4); update_disk_options(new_leader_idx, 8);
// recycle 2 block // recycle 2 block
sleep(5); sleep(5);
block_id_t leader_min_block_id; block_id_t leader_min_block_id;
@ -254,7 +254,7 @@ TEST_F(TestObSimpleLogClusterRebuild, test_old_leader_rebuild)
revert_cluster_palf_handle_guard(palf_list); revert_cluster_palf_handle_guard(palf_list);
EXPECT_EQ(OB_SUCCESS, new_leader.palf_handle_impl_->set_base_lsn(LSN(64*6*MB))); EXPECT_EQ(OB_SUCCESS, new_leader.palf_handle_impl_->set_base_lsn(LSN(64*6*MB)));
sleep(1); sleep(1);
EXPECT_EQ(OB_SUCCESS, update_disk_options(new_leader_idx, 40)); EXPECT_EQ(OB_SUCCESS, update_disk_options(new_leader_idx, 30));
PALF_LOG(INFO, "end test old_leader_rebuild", K(id)); PALF_LOG(INFO, "end test old_leader_rebuild", K(id));
} }
@ -283,11 +283,11 @@ TEST_F(TestObSimpleLogClusterRebuild, test_follower_rebuild)
// the follower is empty // the follower is empty
block_net(leader_idx, follower_idx); block_net(leader_idx, follower_idx);
EXPECT_EQ(OB_SUCCESS, submit_log(leader, 64, leader_idx, MB)); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 64, leader_idx, MB));
EXPECT_EQ(OB_SUCCESS, submit_log(leader, 64 * 5, leader_idx, MB)); EXPECT_EQ(OB_SUCCESS, submit_log(leader, 64 * 7, leader_idx, MB));
// recycle one block // recycle one block
LSN recycle_lsn(2 * PALF_BLOCK_SIZE); LSN recycle_lsn(2 * PALF_BLOCK_SIZE);
EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->set_base_lsn(recycle_lsn)); EXPECT_EQ(OB_SUCCESS, leader.palf_handle_impl_->set_base_lsn(recycle_lsn));
update_disk_options(leader_idx, 4); update_disk_options(leader_idx, 8);
sleep(1); sleep(1);
block_id_t leader_min_block_id, follower_min_block_id; block_id_t leader_min_block_id, follower_min_block_id;
share::SCN min_scn; share::SCN min_scn;

View File

@ -97,6 +97,8 @@ void read_padding_entry(PalfHandleImplGuard &leader, SCN padding_scn, LSN paddin
TEST_F(TestObSimpleLogClusterSingleReplica, delete_paxos_group) TEST_F(TestObSimpleLogClusterSingleReplica, delete_paxos_group)
{ {
update_server_log_disk(10*1024*1024*1024ul);
update_disk_options(10*1024*1024*1024ul/palf::PALF_PHY_BLOCK_SIZE);
SET_CASE_LOG_FILE(TEST_NAME, "delete_paxos_group"); SET_CASE_LOG_FILE(TEST_NAME, "delete_paxos_group");
const int64_t id = ATOMIC_AAF(&palf_id_, 1); const int64_t id = ATOMIC_AAF(&palf_id_, 1);
PALF_LOG(INFO, "start test delete_paxos_group", K(id)); PALF_LOG(INFO, "start test delete_paxos_group", K(id));

View File

@ -158,7 +158,7 @@ int ObServerLogBlockMgr::start(const int64_t new_size_byte)
ret = OB_NOT_INIT; ret = OB_NOT_INIT;
CLOG_LOG(WARN, "ObServerLogBlockMGR is not inited", K(ret), KPC(this)); CLOG_LOG(WARN, "ObServerLogBlockMGR is not inited", K(ret), KPC(this));
} else if (!check_space_is_enough_(new_size_byte)) { } else if (!check_space_is_enough_(new_size_byte)) {
ret = OB_LOG_OUTOF_DISK_SPACE; ret = OB_MACHINE_RESOURCE_NOT_ENOUGH;
CLOG_LOG(WARN, "server log disk is too small to hold all tenants or the count of tenants" CLOG_LOG(WARN, "server log disk is too small to hold all tenants or the count of tenants"
", log disk space is not enough!!!", ", log disk space is not enough!!!",
K(ret), KPC(this), K(min_log_disk_size_for_all_tenants_), K(new_size_byte)); K(ret), KPC(this), K(min_log_disk_size_for_all_tenants_), K(new_size_byte));
@ -189,27 +189,25 @@ int ObServerLogBlockMgr::resize_(const int64_t new_size_byte)
ret = OB_NOT_INIT; ret = OB_NOT_INIT;
CLOG_LOG(ERROR, "ObServerLogBlockMgr has not inited", K(ret), KPC(this), CLOG_LOG(ERROR, "ObServerLogBlockMgr has not inited", K(ret), KPC(this),
K(new_size_byte), K(aligned_new_size_byte)); K(new_size_byte), K(aligned_new_size_byte));
} else if (new_size_byte < share::ObUnitResource::UNIT_MIN_LOG_DISK_SIZE) {
ret = OB_NOT_SUPPORTED;
CLOG_LOG(ERROR, "The size of reserved disp space need greater than 1GB!!!", K(ret),
KPC(this), K(new_size_byte), K(aligned_new_size_byte));
} else if (curr_total_size == aligned_new_size_byte) { } else if (curr_total_size == aligned_new_size_byte) {
CLOG_LOG(TRACE, "no need do resize", K(ret), KPC(this), K(new_size_byte), K(aligned_new_size_byte)); CLOG_LOG(TRACE, "no need do resize", K(ret), KPC(this), K(new_size_byte), K(aligned_new_size_byte));
} else if (FALSE_IT(new_log_pool_meta.status_ = } else if (FALSE_IT(new_log_pool_meta.status_ =
(aligned_new_size_byte > curr_total_size ? EXPANDING_STATUS (aligned_new_size_byte > curr_total_size ? EXPANDING_STATUS
: SHRINKING_STATUS))) { : SHRINKING_STATUS))) {
} else if (SHRINKING_STATUS == new_log_pool_meta.status_ } else if (aligned_new_size_byte < min_log_disk_size_for_all_tenants_) {
&& free_size_byte < resize_block_cnt * BLOCK_SIZE) {
ret = OB_NOT_SUPPORTED; ret = OB_NOT_SUPPORTED;
CLOG_LOG(ERROR, "shrink_block_cnt is greater than free_block_cnt", K(ret), KPC(this), LOG_DBA_ERROR(OB_NOT_SUPPORTED,
K(resize_block_cnt), "free_block_cnt:", free_size_byte / BLOCK_SIZE); "possible reason",
"new log_disk_size is not enough to hold all tenants, please check the configuration about log disk",
"new log disk size(MB)", (new_size_byte+1024*1024-1)/1024/1024,
"min log disk size(MB)", (min_log_disk_size_for_all_tenants_+1024*1024-1)/1024/1024);
} else if (OB_FAIL( } else if (OB_FAIL(
do_resize_(old_log_pool_meta, resize_block_cnt, new_log_pool_meta))) { do_resize_(old_log_pool_meta, resize_block_cnt, new_log_pool_meta))) {
if (OB_ALLOCATE_DISK_SPACE_FAILED == ret) { if (OB_ALLOCATE_DISK_SPACE_FAILED == ret) {
LOG_DBA_ERROR(OB_ALLOCATE_DISK_SPACE_FAILED, LOG_DBA_ERROR(OB_ALLOCATE_DISK_SPACE_FAILED,
"possible reason", "possible reason",
"may be diskspace is not enough, please check the configuration about log disk", "may be diskspace is not enough, please check the configuration about log disk",
"expected log disk size(MB)", (new_size_byte+1024*1024-1)/1024/1024); "new log disk size(MB)", (new_size_byte+1024*1024-1)/1024/1024);
} else { } else {
CLOG_LOG(ERROR, "do_resize_ failed", K(ret), KPC(this), K(old_log_pool_meta), CLOG_LOG(ERROR, "do_resize_ failed", K(ret), KPC(this), K(old_log_pool_meta),
K(new_log_pool_meta)); K(new_log_pool_meta));
@ -343,40 +341,113 @@ void ObServerLogBlockMgr::abort_create_tenant(const int64_t log_disk_size)
} }
} }
int ObServerLogBlockMgr::update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size) int ObServerLogBlockMgr::update_tenant(const int64_t old_log_disk_size,
const int64_t new_log_disk_size,
int64_t &allowed_new_log_disk_size,
logservice::ObLogService *log_service)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
ObSpinLockGuard guard(resize_lock_);
int64_t used_log_disk_size = 0, palf_log_disk_size = 0;
bool can_update_log_disk_size_with_expected_log_disk = false;
int64_t tmp_log_disk_size = min_log_disk_size_for_all_tenants_;
tmp_log_disk_size -= old_log_disk_size;
// 'old_log_disk_size' is current log disk size in ObTenant.
// 'new_log_disk_size' is the latest log disk size record in __all_unit_config.
// 'allowed_new_log_disk_size' is current allowed log disk size when update log disk.
//
// To avoid overselling, we can not use 'new_log_disk_size' to update unit config which will save in slog.
// therefore, we need constuct a virtual log disk size which named with 'allowed_new_log_disk_size'.
if (IS_NOT_INIT) { if (IS_NOT_INIT) {
ret = OB_NOT_INIT; ret = OB_NOT_INIT;
CLOG_LOG(WARN, "ObServerLogBlockMGR is not inited", K(old_log_disk_size), K(new_log_disk_size), KPC(this)); CLOG_LOG(WARN, "ObServerLogBlockMGR is not inited", K(old_log_disk_size), K(new_log_disk_size), KPC(this));
} else { } else if (old_log_disk_size <= 0 || new_log_disk_size <= 0 || OB_ISNULL(log_service)) {
ObSpinLockGuard guard(resize_lock_); ret = OB_INVALID_ARGUMENT;
int64_t tmp_log_disk_size = min_log_disk_size_for_all_tenants_; CLOG_LOG(WARN, "invalid argument", K(old_log_disk_size), K(new_log_disk_size), KP(log_service), KPC(this));
tmp_log_disk_size -= old_log_disk_size; } else if (OB_FAIL(log_service->get_palf_stable_disk_usage(used_log_disk_size, palf_log_disk_size))) {
if ((tmp_log_disk_size +=new_log_disk_size) > get_total_size_guarded_by_lock_()) { CLOG_LOG(WARN, "fail to get_palf_stable_disk_usage", K(old_log_disk_size), K(new_log_disk_size));
// The standard for determing whether it's in shrinking or expanding status:
// 1. If 'palf_log_disk_size' is smaller than or equal to 'new_log_disk_size', it's in expanding status.
// 2. If 'palf_log_disk_size' is greater than 'new_log_disk_size', it's in shrinking status.
//
// For shrinking log disk, we don't update ObTenantConfig of ObTenant to new ObTenantConfig until shrinking successfully.
//
// NB: All fields of new ObTenantConfig except log_disk_size has been updated in case of shrinking log disk.
//
// For example:
// 1. before shrinkg log disk successfully, and then expand log disk.
// - At T1 timestamp, the original log disk is 100G, and update it to 50G, we will construct 'new_unit' with
// 100G, but update palf with 50G because original log disk size is greater than new log disk size.
// - At T2 timestamp, the log disk size in current ObTenantConfig is 100G, and we update it to 80G, there are
// two scenarios:
// 1. if 'palf_log_disk_size' which get from palf is 100G, we think palf is still in shrinking status. and we will
// construct 'new_unit' with 100G because 'palf_log_disk_size' is greater than new log disk size(80G). but udpate
// palf with 80G
// 2. if 'palf_log_disk_size' which get from palf is 50G, we think palf has been in normal status. and we will
// construct 'new_unit' with 80G because 'palf_log_disk_size' is smaller than new log disk size(80G), but udpate
// palf with 80G.
} else if (FALSE_IT(can_update_log_disk_size_with_expected_log_disk = (new_log_disk_size >= palf_log_disk_size))) {
// For expanding log disk, we can update 'allowed_new_log_disk_size' to 'new_log_disk_size' directlly.
} else if (can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = new_log_disk_size)) {
// For shrinking log disk, we still update log disk size of 'new_unit' to 'old_log_disk_size'.
} else if (!can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = old_log_disk_size)) {
} else if ((tmp_log_disk_size += allowed_new_log_disk_size) > get_total_size_guarded_by_lock_()) {
ret = OB_MACHINE_RESOURCE_NOT_ENOUGH; ret = OB_MACHINE_RESOURCE_NOT_ENOUGH;
CLOG_LOG(ERROR, "ObServerLogBlockMGR can not hold any new tenants", CLOG_LOG(WARN, "ObServerLogBlockMGR can not hold any new tenants", KPC(this), K(old_log_disk_size),
K(ret), KPC(this), K(old_log_disk_size), K(new_log_disk_size)); K(new_log_disk_size), K(allowed_new_log_disk_size), K(tmp_log_disk_size));
// case 1: for shrinking log disk, shrinking log disk from 100G to 50G.
// - At T1 timestamp, 'new_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G.
// the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log
// disk which has assigned in ObServerLogBlockMGR.
// - At T2 timestamp, 'new_log_disk_size' is still 50G, 'old_log_disk_size' is still 100G, however, 'allowed_new_log_disk_size'
// is 50G because of shrinking log disk has been successfully, the log disk record in slog is 50G, and then we will update log disk
// size used for palf to 50G again but has no effect, log disk assigned in ObServerLogBlockMGR update to 50G(assume there is only one tenant).
//
// case 2: for expanding log disk, expanding log disk from 100G to 150G.
// - At T1 timestamp, 'new_log_disk_size' is 150G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 150G.
// the log disk size record in slog is 150G, and then, we will update log disk size used for palf to 150G, the log disk
// which has assigned in ObServerLogBlockMGR updaet to 150G(assume there is only one tenant).
//
// case 3: for shrinking log disk, shrinking log disk from 100G to 50G, and then shrinking log disk from 50G to 25G.
// - At T1 timestamp, 'new_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G.
// the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log
// disk which has assigned in ObServerLogBlockMGR.
// - At T2 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is still 100G, however, there are two possibility value for
// 'allowed_new_log_disk_size':
// 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G
// and then we will update log disk size used for palf to 25G, but not update log disk assigned in ObServerLogBlockMGR.
// At T3 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G,
// the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G.
// 2. the value is 50G because of last shrinking log disk has been successfully, the log disk record in slog is 50G
// and then we will update log disk size used for palf to 25G, update log disk assigned in ObServerLogBlockMGR to 50G(assume there is only one tenant).
// At T3 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G,
// the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G.
//
// case 4: for shrinking log disk, shrinking log disk from 100G to 50G, and then expanding log disk from 50G to 80G.
// - At T1 timestamp, 'new_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G.
// the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log
// disk which has assigned in ObServerLogBlockMGR.
// - At T2 timestamp, 'new_log_disk_size' is 80G, 'old_log_disk_size' is still 100G, however, there are two possibility value for
// 'allowed_new_log_disk_size':
// 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G
// and then we will update log disk size used for palf to 80G, but not update log disk assigned in ObServerLogBlockMGR.
// At T3 timestamp, 'new_log_disk_size' is 80G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 80G,
// the log disk record in slog is 80G, the log disk assigned in ObServerLogBlockMGR is 80G.
// 2. the value is 80G because of last shrinking log disk has been successfully, the log disk record in slog is 80G
// and then we will update log disk size used for palf to 80G, update log disk assigned in ObServerLogBlockMGR to 80G(assume there is only one tenant).
// At T3 timestamp, 'new_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G,
// the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G.
//
} else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(new_log_disk_size))) {
CLOG_LOG(WARN, "failed to update_log_disk_usage_limit_size", K(new_log_disk_size), K(old_log_disk_size),
K(allowed_new_log_disk_size));
} else { } else {
min_log_disk_size_for_all_tenants_ = tmp_log_disk_size; min_log_disk_size_for_all_tenants_ = tmp_log_disk_size;
CLOG_LOG(INFO, "ObServerLogBlockMGR update_tenant success", KPC(this), K(old_log_disk_size), K(new_log_disk_size)); CLOG_LOG(INFO, "update_tenant success", KPC(this), K(new_log_disk_size), K(old_log_disk_size),
} K(allowed_new_log_disk_size));
}
return ret;
} }
void ObServerLogBlockMgr::abort_update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size) return ret;
{
if (IS_NOT_INIT) {
CLOG_LOG_RET(WARN, OB_NOT_INIT, "ObServerLogBlockMGR is not inited", K(old_log_disk_size), K(new_log_disk_size), KPC(this));
} else {
ObSpinLockGuard guard(resize_lock_);
min_log_disk_size_for_all_tenants_ -= old_log_disk_size;
min_log_disk_size_for_all_tenants_ += new_log_disk_size;
OB_ASSERT(min_log_disk_size_for_all_tenants_ >= 0
&& min_log_disk_size_for_all_tenants_ <= get_total_size_guarded_by_lock_());
CLOG_LOG(INFO, "ObServerLogBlockMGR abort_update_tenant success", KPC(this), K(old_log_disk_size), K(new_log_disk_size));
}
} }
int ObServerLogBlockMgr::remove_tenant(const int64_t log_disk_size) int ObServerLogBlockMgr::remove_tenant(const int64_t log_disk_size)
@ -696,16 +767,12 @@ int ObServerLogBlockMgr::try_resize()
CLOG_LOG(WARN, "ObServerLogBlockMgr not running, can not support resize", KPC(this)); CLOG_LOG(WARN, "ObServerLogBlockMgr not running, can not support resize", KPC(this));
} else if (OB_FAIL(observer::ObServerUtils::get_log_disk_info_in_config(log_disk_size, } else if (OB_FAIL(observer::ObServerUtils::get_log_disk_info_in_config(log_disk_size,
log_disk_percentage))) { log_disk_percentage))) {
if (OB_LOG_OUTOF_DISK_SPACE == ret) { if (OB_SERVER_OUTOF_DISK_SPACE == ret) {
CLOG_LOG(ERROR, "log disk size is too large", K(ret), KPC(this), ret = OB_MACHINE_RESOURCE_NOT_ENOUGH;
K(log_disk_size), K(log_disk_percentage)); CLOG_LOG(ERROR, "try_resize failed, log disk space is not enough", K(log_disk_size), KPC(this));
} else { } else {
CLOG_LOG(ERROR, "get_log_disk_info_in_config failed", K(ret), KPC(this), CLOG_LOG(ERROR, "get_log_disk_info_in_config failed", K(log_disk_size), KPC(this));
K(log_disk_size), K(log_disk_percentage));
} }
} else if (log_disk_size == get_total_size_guarded_by_lock_()) {
} else if (false == check_space_is_enough_(log_disk_size)) {
CLOG_LOG(ERROR, "log disk size is not enough to hold all tenants", KPC(this), K(log_disk_size));
} else if (OB_FAIL(resize_(log_disk_size))) { } else if (OB_FAIL(resize_(log_disk_size))) {
CLOG_LOG(ERROR, "ObServerLogBlockMGR resize failed", K(ret), KPC(this)); CLOG_LOG(ERROR, "ObServerLogBlockMGR resize failed", K(ret), KPC(this));
} else { } else {

View File

@ -29,7 +29,7 @@ namespace oceanbase
{ {
namespace logservice namespace logservice
{ {
class ObLogService;
class ObServerLogBlockMgr : public palf::ILogBlockPool class ObServerLogBlockMgr : public palf::ILogBlockPool
{ {
public: public:
@ -187,14 +187,14 @@ public:
// @brief before 'update_tenant_log_disk_size' in ObMultiTenant, need update it. // @brief before 'update_tenant_log_disk_size' in ObMultiTenant, need update it.
// @param[in] the log disk size used by tenant. // @param[in] the log disk size used by tenant.
// @param[in] the log disk size need by tenant. // @param[in] the log disk size need by tenant.
// @param[in] the log disk size allowed by tenant
// @param[in] ObLogService*
// OB_SUCCESS // OB_SUCCESS
// OB_MACHINE_RESOURCE_NOT_ENOUGH // OB_MACHINE_RESOURCE_NOT_ENOUGH
int update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size); int update_tenant(const int64_t old_log_disk_size,
const int64_t new_log_disk_size,
// @brief after 'update_tenant_log_disk_size' in ObMultiTenant failed, need rollbakc it. int64_t &allowed_log_disk_size,
// @param[in] the log disk size need by tenant. ObLogService *log_service);
// @param[in] the log disk size used by tenant.
void abort_update_tenant(const int64_t old_log_disk_size, const int64_t new_log_disk_size);
// @brief after 'del_tenant' in ObMultiTenant success, need remove it from ObServerLogBlockMgr // @brief after 'del_tenant' in ObMultiTenant success, need remove it from ObServerLogBlockMgr
// NB: accurately, when tenant not exist in 'omt_', we can remove it from ObServerLogBlockMgr // NB: accurately, when tenant not exist in 'omt_', we can remove it from ObServerLogBlockMgr

View File

@ -169,7 +169,6 @@ int PalfDiskOptionsWrapper::update_disk_options_not_guarded_by_lock_(const PalfD
disk_opts_for_stopping_writing_.log_disk_throttling_percentage_ = new_trigger_percentage; disk_opts_for_stopping_writing_.log_disk_throttling_percentage_ = new_trigger_percentage;
disk_opts_for_recycling_blocks_.log_disk_throttling_maximum_duration_ = new_maximum_duration; disk_opts_for_recycling_blocks_.log_disk_throttling_maximum_duration_ = new_maximum_duration;
disk_opts_for_stopping_writing_.log_disk_throttling_maximum_duration_ = new_maximum_duration; disk_opts_for_stopping_writing_.log_disk_throttling_maximum_duration_ = new_maximum_duration;
sequence_++; sequence_++;
} }
return ret; return ret;
@ -404,7 +403,7 @@ int PalfEnvImpl::create_palf_handle_impl_(const int64_t palf_id,
PALF_LOG(WARN, "palf_handle has exist, ignore this request", K(ret), K(palf_id)); PALF_LOG(WARN, "palf_handle has exist, ignore this request", K(ret), K(palf_id));
} else if (false == check_can_create_palf_handle_impl_()) { } else if (false == check_can_create_palf_handle_impl_()) {
ret = OB_LOG_OUTOF_DISK_SPACE; ret = OB_LOG_OUTOF_DISK_SPACE;
PALF_LOG(ERROR, "PalfEnv can not hold more instance", K(ret), KPC(this), K(palf_id)); PALF_LOG(WARN, "PalfEnv can not hold more instance", K(ret), KPC(this), K(palf_id));
} else if (0 > (pret = snprintf(base_dir, MAX_PATH_SIZE, "%s/%ld", log_dir_, palf_id))) { } else if (0 > (pret = snprintf(base_dir, MAX_PATH_SIZE, "%s/%ld", log_dir_, palf_id))) {
ret = OB_ERR_UNEXPECTED; ret = OB_ERR_UNEXPECTED;
PALF_LOG(ERROR, "snprinf failed", K(pret), K(palf_id)); PALF_LOG(ERROR, "snprinf failed", K(pret), K(palf_id));
@ -709,6 +708,11 @@ int PalfEnvImpl::try_recycle_blocks()
const bool curr_diskspace_enough = const bool curr_diskspace_enough =
usable_disk_limit_size_to_stop_writing > total_used_size_byte ? true : false; usable_disk_limit_size_to_stop_writing > total_used_size_byte ? true : false;
constexpr int64_t MB = 1024 * 1024LL; constexpr int64_t MB = 1024 * 1024LL;
const int64_t print_error_log_disk_size =
disk_opts_for_stopping_writing.log_disk_usage_limit_size_
* disk_opts_for_stopping_writing.log_disk_utilization_threshold_;
const bool need_print_error_log =
print_error_log_disk_size > total_used_size_byte ? false : true;
// step1. change SHRINKING_STATUS to normal // step1. change SHRINKING_STATUS to normal
// 1. when there is no possibility to stop writing, // 1. when there is no possibility to stop writing,
@ -736,7 +740,11 @@ int PalfEnvImpl::try_recycle_blocks()
if (diskspace_enough_ != curr_diskspace_enough) { if (diskspace_enough_ != curr_diskspace_enough) {
ATOMIC_STORE(&diskspace_enough_, curr_diskspace_enough); ATOMIC_STORE(&diskspace_enough_, curr_diskspace_enough);
} }
if ((true == need_recycle && false == has_recycled && false == is_shrinking) || false == diskspace_enough_) {
// NB: print error log when:
// 1. write-stop.
// 2. the used log disk space exceeded the log disk recycle threshold(stop-write PalfDiskOptions) and there is no recycable block.
if ((false == diskspace_enough_) || (true == need_print_error_log && false == has_recycled)) {
constexpr int64_t INTERVAL = 1*1000*1000; constexpr int64_t INTERVAL = 1*1000*1000;
if (palf_reach_time_interval(INTERVAL, disk_not_enough_print_interval_)) { if (palf_reach_time_interval(INTERVAL, disk_not_enough_print_interval_)) {
int tmp_ret = OB_LOG_OUTOF_DISK_SPACE; int tmp_ret = OB_LOG_OUTOF_DISK_SPACE;
@ -886,13 +894,15 @@ int PalfEnvImpl::update_options(const PalfOptions &options)
} else if (false == options.is_valid()) { } else if (false == options.is_valid()) {
ret = OB_INVALID_ARGUMENT; ret = OB_INVALID_ARGUMENT;
PALF_LOG(WARN, "invalid argument", K(options)); PALF_LOG(WARN, "invalid argument", K(options));
} else if (OB_FAIL(disk_options_wrapper_.update_disk_options(options.disk_options_))) {
PALF_LOG(WARN, "update_disk_options failed", K(ret), K(options));
} else if (OB_FAIL(log_rpc_.update_transport_compress_options(options.compress_options_))) { } else if (OB_FAIL(log_rpc_.update_transport_compress_options(options.compress_options_))) {
PALF_LOG(WARN, "update_transport_compress_options failed", K(ret), K(options)); PALF_LOG(WARN, "update_transport_compress_options failed", K(ret), K(options));
} else if (FALSE_IT(rebuild_replica_log_lag_threshold_ = options.rebuild_replica_log_lag_threshold_)) {
} else if (OB_FAIL(check_can_update_log_disk_options_(options.disk_options_))) {
PALF_LOG(WARN, "check_can_update_log_disk_options_ failed", K(options));
} else if (OB_FAIL(disk_options_wrapper_.update_disk_options(options.disk_options_))) {
PALF_LOG(WARN, "update_disk_options failed", K(ret), K(options));
} else { } else {
rebuild_replica_log_lag_threshold_ = options.rebuild_replica_log_lag_threshold_; PALF_LOG(INFO, "update_options successs", K(options), KPC(this));
PALF_LOG(INFO, "update_palf_options success", K(options));
} }
return ret; return ret;
} }
@ -1315,5 +1325,18 @@ int PalfEnvImpl::init_log_io_worker_config_(const int log_writer_parallelism,
return ret; return ret;
} }
int PalfEnvImpl::check_can_update_log_disk_options_(const PalfDiskOptions &disk_opts)
{
int ret = OB_SUCCESS;
const int64_t curr_palf_instance_num = palf_handle_impl_map_.count();
const int64_t curr_min_log_disk_size = curr_palf_instance_num * MIN_DISK_SIZE_PER_PALF_INSTANCE;
if (disk_opts.log_disk_usage_limit_size_ < curr_min_log_disk_size) {
ret = OB_NOT_SUPPORTED;
PALF_LOG(WARN, "can not hold current palf instance", K(curr_palf_instance_num),
K(curr_min_log_disk_size), K(disk_opts));
}
return ret;
}
} // end namespace palf } // end namespace palf
} // end namespace oceanbase } // end namespace oceanbase

View File

@ -346,6 +346,8 @@ private:
const int64_t tenant_id, const int64_t tenant_id,
LogIOWorkerConfig &config); LogIOWorkerConfig &config);
int check_can_update_log_disk_options_(const PalfDiskOptions &disk_options);
private: private:
typedef common::RWLock RWLock; typedef common::RWLock RWLock;
typedef RWLock::RLockGuard RLockGuard; typedef RWLock::RLockGuard RLockGuard;

View File

@ -51,158 +51,102 @@ int ObServerUtils::get_server_ip(ObIAllocator *allocator, ObString &ipstr)
int ObServerUtils::get_log_disk_info_in_config(int64_t& log_disk_size, int ObServerUtils::get_log_disk_info_in_config(int64_t& log_disk_size,
int64_t& log_disk_percentage) int64_t& log_disk_percentage)
{ {
int64_t data_disk_size = 0; int ret = OB_SUCCESS;
int64_t data_disk_percentage = 0; int64_t suggested_data_disk_size = GCONF.datafile_size;
int64_t suggested_data_disk_percentage = GCONF.datafile_disk_percentage;
return observer::ObServerUtils::cal_all_part_disk_size(GCONF.datafile_size, int64_t suggested_clog_disk_size = GCONF.log_disk_size;
GCONF.log_disk_size, int64_t suggested_clog_disk_percentage = GCONF.log_disk_percentage;
GCONF.datafile_disk_percentage, int64_t data_default_disk_percentage = 0;
GCONF.log_disk_percentage, int64_t clog_default_disk_percentage = 0;
data_disk_size, int64_t data_disk_total_size = 0;
int64_t clog_disk_total_size = 0;
bool shared_mode = false;
const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir();
const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir();
if (OB_FAIL(cal_all_part_disk_default_percentage(data_disk_total_size,
data_default_disk_percentage,
clog_disk_total_size,
clog_default_disk_percentage,
shared_mode))) {
LOG_ERROR("cal all part disk default percentage failed",
KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(data_default_disk_percentage), K(shared_mode));
} else if (OB_FAIL(decide_disk_size(clog_disk_total_size,
suggested_clog_disk_size,
suggested_clog_disk_percentage,
clog_default_disk_percentage,
log_disk_size, log_disk_size,
data_disk_percentage, log_disk_percentage))) {
log_disk_percentage); LOG_ERROR("decide disk size failed",
KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(data_default_disk_percentage), K(shared_mode));
} else {
LOG_INFO("get_log_disk_info_in_config", K(suggested_data_disk_size), K(suggested_clog_disk_size),
K(suggested_data_disk_percentage), K(suggested_clog_disk_percentage), K(log_disk_size),
K(log_disk_percentage));
}
return ret;
} }
int ObServerUtils::get_data_disk_info_in_config(int64_t& data_disk_size, int ObServerUtils::get_data_disk_info_in_config(int64_t& data_disk_size,
int64_t& data_disk_percentage) int64_t& data_disk_percentage)
{ {
int64_t log_disk_size = 0; int ret = OB_SUCCESS;
int64_t log_disk_percentage = 0; int64_t suggested_data_disk_size = GCONF.datafile_size;
int64_t suggested_data_disk_percentage = GCONF.datafile_disk_percentage;
return observer::ObServerUtils::cal_all_part_disk_size(GCONF.datafile_size, int64_t suggested_clog_disk_size = GCONF.log_disk_size;
GCONF.log_disk_size, int64_t suggested_clog_disk_percentage = GCONF.log_disk_percentage;
GCONF.datafile_disk_percentage, int64_t data_default_disk_percentage = 0;
GCONF.log_disk_percentage, int64_t clog_default_disk_percentage = 0;
int64_t data_disk_total_size = 0;
int64_t clog_disk_total_size = 0;
bool shared_mode = false;
const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir();
const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir();
if (OB_FAIL(cal_all_part_disk_default_percentage(data_disk_total_size,
data_default_disk_percentage,
clog_disk_total_size,
clog_default_disk_percentage,
shared_mode))) {
LOG_ERROR("cal all part disk default percentage failed",
KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(data_default_disk_percentage), K(shared_mode));
} else if (OB_FAIL(decide_disk_size(data_disk_total_size,
suggested_data_disk_size,
suggested_data_disk_percentage,
data_default_disk_percentage,
data_disk_size, data_disk_size,
log_disk_size, data_disk_percentage))) {
data_disk_percentage, LOG_ERROR("decide data disk size failed",
log_disk_percentage); KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(data_default_disk_percentage), K(shared_mode));
} else {
LOG_INFO("get_data_disk_info_in_config", K(suggested_data_disk_size), K(suggested_clog_disk_size),
K(suggested_data_disk_percentage), K(suggested_clog_disk_percentage), K(data_disk_size),
K(data_disk_percentage));
}
return ret;
} }
int ObServerUtils::cal_all_part_disk_size(const int64_t suggested_data_disk_size, int ObServerUtils::cal_all_part_disk_size(const int64_t suggested_data_disk_size,
const int64_t suggested_log_disk_size, const int64_t suggested_clog_disk_size,
const int64_t suggested_data_disk_percentage, const int64_t suggested_data_disk_percentage,
const int64_t suggested_log_disk_percentage, const int64_t suggested_clog_disk_percentage,
int64_t& data_disk_size, int64_t& data_disk_size,
int64_t& log_disk_size, int64_t& log_disk_size,
int64_t& data_disk_percentage, int64_t& data_disk_percentage,
int64_t& log_disk_percentage) int64_t& log_disk_percentage)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
if (OB_FAIL(get_data_disk_info_in_config(data_disk_size, data_disk_percentage))) {
// background information about default disk percentage: LOG_ERROR("get_data_disk_info_in_config failed", K(data_disk_size), K(data_disk_percentage));
// If not in shared mode, disk will be used up to 90%. } else if (OB_FAIL(get_log_disk_info_in_config(log_disk_size, log_disk_percentage))) {
// If in shared mode, data and clog disk usage will be up to 60% and 30% LOG_ERROR("get_log_disk_info_in_config failed", K(log_disk_size), K(log_disk_percentage));
const int64_t DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE = 90;
const int64_t DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE = 60;
const int64_t DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE = 30;
// We use sstable_dir as the data disk directory to identify whether the log and data are located
// on the same file system, and the storage module will ensure that sstable_dir and slog_dir are
// located on the same file system;
const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir();
const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir();
struct statvfs data_statvfs;
struct statvfs clog_statvfs;
if (OB_SUCC(ret)) {
if (OB_UNLIKELY(0 != statvfs(data_dir, &data_statvfs))) {
LOG_ERROR("Failed to get data disk space ", KR(ret), K(data_dir), K(errno));
ret = OB_ERR_UNEXPECTED;
} else if (OB_UNLIKELY(0 != statvfs(clog_dir, &clog_statvfs))) {
LOG_ERROR("Failed to get clog disk space ", KR(ret), K(clog_dir), K(errno));
ret = OB_ERR_UNEXPECTED;
}
}
bool shared_mode = true;
int64_t data_default_disk_percentage = 0;
int64_t clog_default_disk_percentage = 0;
if (OB_SUCC(ret)) {
if (data_statvfs.f_fsid == clog_statvfs.f_fsid) {
shared_mode = true;
data_default_disk_percentage = DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE;
clog_default_disk_percentage = DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE;
} else { } else {
shared_mode = false; LOG_INFO("cal_all_part_disk_size success", K(suggested_data_disk_size), K(suggested_clog_disk_size),
data_default_disk_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE; K(suggested_data_disk_percentage), K(suggested_clog_disk_percentage), K(data_disk_size),
clog_default_disk_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE; K(log_disk_size), K(data_disk_percentage), K(log_disk_percentage));
} }
if (OB_FAIL(decide_disk_size(data_statvfs,
suggested_data_disk_size,
suggested_data_disk_percentage,
data_default_disk_percentage,
data_dir,
data_disk_size,
data_disk_percentage))) {
LOG_ERROR("decide data disk size failed",
KR(ret), K(data_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(data_default_disk_percentage), K(shared_mode));
} else if (OB_FAIL(decide_disk_size(clog_statvfs,
suggested_log_disk_size,
suggested_log_disk_percentage,
clog_default_disk_percentage,
clog_dir,
log_disk_size,
log_disk_percentage))) {
LOG_ERROR("decide clog disk size failed",
KR(ret), K(clog_dir), K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(clog_default_disk_percentage), K(shared_mode));
}
}
if (OB_FAIL(ret)) {
LOG_ERROR("decide_all_disk_size failed",
KR(ret), K(data_dir), K(clog_dir),
K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(data_default_disk_percentage), K(clog_default_disk_percentage),
K(shared_mode), K(data_disk_size), K(log_disk_size));
} else {
LOG_INFO("decide_all_disk_size succ",
K(data_dir), K(clog_dir),
K(suggested_data_disk_size), K(suggested_data_disk_percentage),
K(data_default_disk_percentage), K(clog_default_disk_percentage),
K(shared_mode), K(data_disk_size), K(log_disk_size));
}
return ret;
}
int ObServerUtils::decide_disk_size(const struct statvfs& svfs,
const int64_t suggested_disk_size,
const int64_t suggested_disk_percentage,
const int64_t default_disk_percentage,
const char* dir,
int64_t& disk_size,
int64_t& disk_percentage)
{
int ret = OB_SUCCESS;
int64_t total_space = (svfs.f_blocks + svfs.f_bavail - svfs.f_bfree) * svfs.f_bsize;
int64_t free_space = svfs.f_bavail * svfs.f_bsize;
if (suggested_disk_size <= 0) {
int64_t disk_percentage = 0;
if (suggested_disk_percentage <= 0) {
disk_percentage = default_disk_percentage;
} else {
disk_percentage = suggested_disk_percentage;
}
disk_size = total_space * disk_percentage / 100;
} else {
disk_size = suggested_disk_size;
}
if (disk_size > total_space) {
ret = OB_SERVER_OUTOF_DISK_SPACE;
}
LOG_INFO("decide disk size finished",
K(dir),
K(suggested_disk_size), K(suggested_disk_percentage),
K(default_disk_percentage),
K(total_space), K(free_space), K(disk_size));
return ret; return ret;
} }
@ -327,6 +271,91 @@ int ObServerUtils::calc_auto_extend_size(int64_t &actual_extend_size)
return ret; return ret;
} }
int ObServerUtils::cal_all_part_disk_default_percentage(int64_t& data_disk_total_size,
int64_t& data_disk_default_percentage,
int64_t& clog_disk_total_size,
int64_t& clog_disk_default_percentage,
bool &shared_mode)
{
int ret = OB_SUCCESS;
// background information about default disk percentage:
// If not in shared mode, disk will be used up to 90%.
// If in shared mode, data and clog disk usage will be up to 60% and 30%
const int64_t DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE = 90;
const int64_t DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE = 60;
const int64_t DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE = 30;
// We use sstable_dir as the data disk directory to identify whether the log and data are located
// on the same file system, and the storage module will ensure that sstable_dir and slog_dir are
// located on the same file system;
const char* data_dir = OB_FILE_SYSTEM_ROUTER.get_sstable_dir();
const char* clog_dir = OB_FILE_SYSTEM_ROUTER.get_clog_dir();
struct statvfs data_statvfs;
struct statvfs clog_statvfs;
if (OB_SUCC(ret)) {
if (OB_UNLIKELY(0 != statvfs(data_dir, &data_statvfs))) {
LOG_ERROR("Failed to get data disk space ", KR(ret), K(data_dir), K(errno));
ret = OB_ERR_UNEXPECTED;
} else if (OB_UNLIKELY(0 != statvfs(clog_dir, &clog_statvfs))) {
LOG_ERROR("Failed to get clog disk space ", KR(ret), K(clog_dir), K(errno));
ret = OB_ERR_UNEXPECTED;
}
}
if (OB_SUCC(ret)) {
if (data_statvfs.f_fsid == clog_statvfs.f_fsid) {
shared_mode = true;
data_disk_default_percentage = DEFAULT_DATA_DISK_PERCENTAGE_IN_SHARED_MODE;
clog_disk_default_percentage = DEFAULT_CLOG_DISK_PERCENTAGE_IN_SHARED_MODE;
} else {
shared_mode = false;
data_disk_default_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE;
clog_disk_default_percentage = DEFAULT_DISK_PERCENTAGE_IN_SEPRATE_MODE;
}
data_disk_total_size = (data_statvfs.f_blocks + data_statvfs.f_bavail - data_statvfs.f_bfree) * data_statvfs.f_bsize;
clog_disk_total_size = (clog_statvfs.f_blocks + clog_statvfs.f_bavail - clog_statvfs.f_bfree) * clog_statvfs.f_bsize;
LOG_INFO("cal_all_part_disk_default_percentage succ",
K(data_dir), K(clog_dir),
K(shared_mode), K(data_disk_total_size), K(data_disk_default_percentage),
K(clog_disk_total_size), K(clog_disk_default_percentage));
}
return ret;
}
int ObServerUtils::decide_disk_size(const int64_t total_space,
const int64_t suggested_disk_size,
const int64_t suggested_disk_percentage,
const int64_t default_disk_percentage,
int64_t& disk_size,
int64_t& disk_percentage)
{
int ret = OB_SUCCESS;
if (suggested_disk_size <= 0) {
int64_t disk_percentage = 0;
if (suggested_disk_percentage <= 0) {
disk_percentage = default_disk_percentage;
} else {
disk_percentage = suggested_disk_percentage;
}
disk_size = total_space * disk_percentage / 100;
} else {
disk_size = suggested_disk_size;
}
if (disk_size > total_space) {
ret = OB_SERVER_OUTOF_DISK_SPACE;
}
LOG_INFO("decide disk size finished",
K(suggested_disk_size), K(suggested_disk_percentage),
K(default_disk_percentage),
K(total_space), K(disk_size));
return ret;
}
} // namespace observer } // namespace observer
} // namespace oceanbase } // namespace oceanbase

View File

@ -71,6 +71,17 @@ private:
const char* dir, const char* dir,
int64_t& disk_size, int64_t& disk_size,
int64_t& disk_percentage); int64_t& disk_percentage);
static int decide_disk_size(const int64_t disk_total_size,
const int64_t suggested_disk_size,
const int64_t suggested_disk_percentage,
const int64_t default_disk_percentage,
int64_t& disk_size,
int64_t& disk_percentage);
static int cal_all_part_disk_default_percentage(int64_t &data_disk_total_size,
int64_t& data_disk_percentage,
int64_t &log_disk_total_size,
int64_t& log_disk_percentage,
bool &shared_mode);
DISALLOW_COPY_AND_ASSIGN(ObServerUtils); DISALLOW_COPY_AND_ASSIGN(ObServerUtils);
}; };
} // namespace observer } // namespace observer

View File

@ -1019,8 +1019,8 @@ int ObMultiTenant::update_tenant_unit_no_lock(const ObUnitInfoGetter::ObTenantCo
} else if (OB_FAIL(update_tenant_memory(tenant_id, unit.config_.memory_size(), allowed_mem_limit))) { } else if (OB_FAIL(update_tenant_memory(tenant_id, unit.config_.memory_size(), allowed_mem_limit))) {
LOG_WARN("fail to update tenant memory", K(ret), K(tenant_id)); LOG_WARN("fail to update tenant memory", K(ret), K(tenant_id));
} else if (OB_FAIL(update_tenant_log_disk_size(tenant_id, } else if (OB_FAIL(update_tenant_log_disk_size(tenant_id,
unit.config_.log_disk_size(),
old_unit.config_.log_disk_size(), old_unit.config_.log_disk_size(),
unit.config_.log_disk_size(),
allowed_new_log_disk_size))) { allowed_new_log_disk_size))) {
LOG_WARN("fail to update tenant log disk size", K(ret), K(tenant_id)); LOG_WARN("fail to update tenant log disk size", K(ret), K(tenant_id));
} else if (OB_FAIL(construct_allowed_unit_config(allowed_new_log_disk_size, } else if (OB_FAIL(construct_allowed_unit_config(allowed_new_log_disk_size,
@ -1154,104 +1154,23 @@ int ObMultiTenant::update_tenant_memory(const uint64_t tenant_id, const int64_t
} }
int ObMultiTenant::update_tenant_log_disk_size(const uint64_t tenant_id, int ObMultiTenant::update_tenant_log_disk_size(const uint64_t tenant_id,
const int64_t expected_log_disk_size,
const int64_t old_log_disk_size, const int64_t old_log_disk_size,
const int64_t new_log_disk_size,
int64_t &allowed_new_log_disk_size) int64_t &allowed_new_log_disk_size)
{ {
int ret = OB_SUCCESS; int ret = OB_SUCCESS;
int64_t used_log_disk_size = 0, palf_log_disk_size = 0;
bool can_update_log_disk_size_with_expected_log_disk = false;
// 'expected_log_disk_size' is the latest log disk size record in __all_unit_config.
// 'old_log_disk_size' is current log disk size in ObTenant.
// 'allowed_new_log_disk_size' is current allowed log disk size when update log disk.
//
// To avoid overselling, we can not use 'expected_log_disk_size' to update unit config which will save in slog.
// therefore, we need constuct a virtual log disk size which named with 'allowed_new_log_disk_size'.
MAKE_TENANT_SWITCH_SCOPE_GUARD(guard); MAKE_TENANT_SWITCH_SCOPE_GUARD(guard);
if (OB_SUCC(guard.switch_to(tenant_id))) { if (OB_SUCC(guard.switch_to(tenant_id))) {
ObLogService *log_service = MTL(ObLogService *); ObLogService *log_service = MTL(ObLogService *);
if (OB_ISNULL(log_service)) { if (OB_ISNULL(log_service)) {
ret = OB_ERR_UNEXPECTED; ret = OB_ERR_UNEXPECTED;
} else if (OB_FAIL(log_service->get_palf_stable_disk_usage(used_log_disk_size, palf_log_disk_size))) { } else if (OB_FAIL(GCTX.log_block_mgr_->update_tenant(old_log_disk_size, new_log_disk_size,
LOG_WARN("fail to get_palf_stable_disk_usage", K(tenant_id), K(old_log_disk_size), K(expected_log_disk_size)); allowed_new_log_disk_size, log_service))) {
// The standard for determing whether it's in shrinking or expanding status: LOG_WARN("fail to update_tenant", K(tenant_id), K(old_log_disk_size), K(new_log_disk_size),
// 1. If 'palf_log_disk_size' is smaller than or equal to 'expected_log_disk_size', it's in expanding status. K(allowed_new_log_disk_size));
// 2. If 'palf_log_disk_size' is greater than 'expected_log_disk_size', it's in shrinking status.
//
// For shrinking log disk, we don't update ObTenantConfig of ObTenant to new ObTenantConfig until shrinking successfully.
//
// NB: All fields of new ObTenantConfig except log_disk_size has been updated in case of shrinking log disk.
//
// For example:
// 1. before shrinkg log disk successfully, and then expand log disk.
// - At T1 timestamp, the original log disk is 100G, and update it to 50G, we will construct 'new_unit' with
// 100G, but update palf with 50G because original log disk size is greater than new log disk size.
// - At T2 timestamp, the log disk size in current ObTenantConfig is 100G, and we update it to 80G, there are
// two scenarios:
// 1. if 'palf_log_disk_size' which get from palf is 100G, we think palf is still in shrinking status. and we will
// construct 'new_unit' with 100G because 'palf_log_disk_size' is greater than new log disk size(80G). but udpate
// palf with 80G
// 2. if 'palf_log_disk_size' which get from palf is 50G, we think palf has been in normal status. and we will
// construct 'new_unit' with 80G because 'palf_log_disk_size' is smaller than new log disk size(80G), but udpate
// palf with 80G.
} else if (FALSE_IT(can_update_log_disk_size_with_expected_log_disk = (expected_log_disk_size >= palf_log_disk_size))) {
// For expanding log disk, we can update 'allowed_new_log_disk_size' to 'expected_log_disk_size' directlly.
} else if (can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = expected_log_disk_size)) {
// For shrinking log disk, we still update log disk size of 'new_unit' to 'old_log_disk_size'.
} else if (!can_update_log_disk_size_with_expected_log_disk && FALSE_IT(allowed_new_log_disk_size = old_log_disk_size)) {
// case 1: for shrinking log disk, shrinking log disk from 100G to 50G.
// - At T1 timestamp, 'expected_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G.
// the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log
// disk which has assigned in ObServerLogBlockMGR.
// - At T2 timestamp, 'expected_log_disk_size' is still 50G, 'old_log_disk_size' is still 100G, however, 'allowed_new_log_disk_size'
// is 50G because of shrinking log disk has been successfully, the log disk record in slog is 50G, and then we will update log disk
// size used for palf to 50G again but has no effect, log disk assigned in ObServerLogBlockMGR update to 50G(assume there is only one tenant).
//
// case 2: for expanding log disk, expanding log disk from 100G to 150G.
// - At T1 timestamp, 'expected_log_disk_size' is 150G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 150G.
// the log disk size record in slog is 150G, and then, we will update log disk size used for palf to 150G, the log disk
// which has assigned in ObServerLogBlockMGR updaet to 150G(assume there is only one tenant).
//
// case 3: for shrinking log disk, shrinking log disk from 100G to 50G, and then shrinking log disk from 50G to 25G.
// - At T1 timestamp, 'expected_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G.
// the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log
// disk which has assigned in ObServerLogBlockMGR.
// - At T2 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is still 100G, however, there are two possibility value for
// 'allowed_new_log_disk_size':
// 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G
// and then we will update log disk size used for palf to 25G, but not update log disk assigned in ObServerLogBlockMGR.
// At T3 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G,
// the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G.
// 2. the value is 50G because of last shrinking log disk has been successfully, the log disk record in slog is 50G
// and then we will update log disk size used for palf to 25G, update log disk assigned in ObServerLogBlockMGR to 50G(assume there is only one tenant).
// At T3 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G,
// the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G.
//
// case 4: for shrinking log disk, shrinking log disk from 100G to 50G, and then expanding log disk from 50G to 80G.
// - At T1 timestamp, 'expected_log_disk_size' is 50G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 100G.
// the log disk size record in slog is 100G, and we will update log disk size used for palf to 50G, but not update log
// disk which has assigned in ObServerLogBlockMGR.
// - At T2 timestamp, 'expected_log_disk_size' is 80G, 'old_log_disk_size' is still 100G, however, there are two possibility value for
// 'allowed_new_log_disk_size':
// 1. the value is 100G because of last shrinking log disk has not been successfully, the log disk record in slog is still 100G
// and then we will update log disk size used for palf to 80G, but not update log disk assigned in ObServerLogBlockMGR.
// At T3 timestamp, 'expected_log_disk_size' is 80G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 80G,
// the log disk record in slog is 80G, the log disk assigned in ObServerLogBlockMGR is 80G.
// 2. the value is 80G because of last shrinking log disk has been successfully, the log disk record in slog is 80G
// and then we will update log disk size used for palf to 80G, update log disk assigned in ObServerLogBlockMGR to 80G(assume there is only one tenant).
// At T3 timestamp, 'expected_log_disk_size' is 25G, 'old_log_disk_size' is 100G, 'allowed_new_log_disk_size' is 25G,
// the log disk record in slog is 25G, the log disk assigned in ObServerLogBlockMGR is 25G.
//
} else if (OB_FAIL(GCTX.log_block_mgr_->update_tenant(old_log_disk_size, allowed_new_log_disk_size))) {
LOG_WARN("failed to update teannt int ObServerLogBlockMGR", K(ret), K(tenant_id), K(expected_log_disk_size),
K(old_log_disk_size), K(allowed_new_log_disk_size));
} else if (OB_FAIL(log_service->update_log_disk_usage_limit_size(expected_log_disk_size))) {
LOG_WARN("failed to update_log_disk_usage_limit_size", K(ret), K(tenant_id), K(expected_log_disk_size),
K(old_log_disk_size), K(allowed_new_log_disk_size));
GCTX.log_block_mgr_->abort_update_tenant(allowed_new_log_disk_size, old_log_disk_size);
} else { } else {
LOG_INFO("update_log_disk_usage_limit_size success", K(ret), K(tenant_id), K(expected_log_disk_size), LOG_INFO("update_tenant_log_disk_size success", K(tenant_id), K(old_log_disk_size),
K(old_log_disk_size), K(allowed_new_log_disk_size)); K(new_log_disk_size), K(allowed_new_log_disk_size));
} }
} }
return ret; return ret;

View File

@ -112,8 +112,8 @@ public:
int update_tenant_memory(const uint64_t tenant_id, const int64_t mem_limit, int64_t &allowed_mem_limit); int update_tenant_memory(const uint64_t tenant_id, const int64_t mem_limit, int64_t &allowed_mem_limit);
int update_tenant_memory(const share::ObUnitInfoGetter::ObTenantConfig &unit); int update_tenant_memory(const share::ObUnitInfoGetter::ObTenantConfig &unit);
int update_tenant_log_disk_size(const uint64_t tenant_id, int update_tenant_log_disk_size(const uint64_t tenant_id,
const int64_t expected_log_disk_size,
const int64_t old_log_disk_size, const int64_t old_log_disk_size,
const int64_t new_log_disk_size,
int64_t &allowed_log_disk_size); int64_t &allowed_log_disk_size);
int modify_tenant_io(const uint64_t tenant_id, const share::ObUnitConfig &unit_config); int modify_tenant_io(const uint64_t tenant_id, const share::ObUnitConfig &unit_config);
int update_tenant_config(uint64_t tenant_id); int update_tenant_config(uint64_t tenant_id);

View File

@ -16,12 +16,14 @@
#include "observer/omt/ob_multi_tenant.h" #include "observer/omt/ob_multi_tenant.h"
#include "observer/omt/ob_tenant.h" #include "observer/omt/ob_tenant.h"
#include "share/ob_unit_getter.h" #include "share/ob_unit_getter.h"
#include "logservice/ob_log_service.h"
using namespace oceanbase; using namespace oceanbase;
using namespace oceanbase::common; using namespace oceanbase::common;
using namespace oceanbase::storage; using namespace oceanbase::storage;
using namespace oceanbase::observer; using namespace oceanbase::observer;
using namespace oceanbase::omt; using namespace oceanbase::omt;
using namespace logservice;
ObAllVirtualUnit::ObAllVirtualUnit() ObAllVirtualUnit::ObAllVirtualUnit()
: ObVirtualTableScannerIterator(), : ObVirtualTableScannerIterator(),
@ -244,9 +246,9 @@ int ObAllVirtualUnit::inner_get_next_row(ObNewRow *&row)
break; break;
case LOG_DISK_IN_USE: { case LOG_DISK_IN_USE: {
int64_t clog_disk_in_use = 0; int64_t clog_disk_in_use = 0;
if (OB_FAIL(static_cast<ObDiskUsageReportTask*>(GCTX.disk_reporter_) const uint64_t tenant_id = tenant_meta.unit_.tenant_id_;
->get_clog_disk_used_size(tenant_meta.unit_.tenant_id_, clog_disk_in_use))) { if (OB_FAIL(get_clog_disk_used_size_(tenant_id, clog_disk_in_use))) {
SERVER_LOG(WARN, "fail to get data disk in use", K(ret), K(tenant_meta)); SERVER_LOG(WARN, "fail to get clog disk in use", K(ret), K(tenant_meta));
} else { } else {
cur_row_.cells_[i].set_int(clog_disk_in_use); cur_row_.cells_[i].set_int(clog_disk_in_use);
} }
@ -284,5 +286,25 @@ int ObAllVirtualUnit::inner_get_next_row(ObNewRow *&row)
return ret; return ret;
} }
int ObAllVirtualUnit::get_clog_disk_used_size_(const uint64_t tenant_id,
int64_t &log_used_size)
{
int ret = OB_SUCCESS;
log_used_size = 0;
MAKE_TENANT_SWITCH_SCOPE_GUARD(guard);
if (OB_SUCC(guard.switch_to(tenant_id))) {
ObLogService *log_service = MTL(ObLogService*);
int64_t unused_log_disk_total_size = 0;
if (OB_ISNULL(log_service)) {
ret = OB_ERR_UNEXPECTED;
SERVER_LOG(WARN, "ObLogService is nullptr", KP(log_service), K(tenant_id));
} else if (OB_FAIL(log_service->get_palf_stable_disk_usage(log_used_size,
unused_log_disk_total_size))) {
SERVER_LOG(WARN, "get_palf_stable_disk_usage failed", KP(log_service), K(tenant_id));
}
}
// return OB_SUCCESS whatever.
return OB_SUCCESS;
}

View File

@ -53,7 +53,8 @@ public:
virtual int inner_open(); virtual int inner_open();
virtual void reset(); virtual void reset();
virtual int inner_get_next_row(common::ObNewRow *&row); virtual int inner_get_next_row(common::ObNewRow *&row);
private:
int get_clog_disk_used_size_(const uint64_t tenant_id, int64_t &log_used_size);
private: private:
char ip_buf_[common::OB_IP_STR_BUFF]; char ip_buf_[common::OB_IP_STR_BUFF];
common::ObAddr addr_; common::ObAddr addr_;

View File

@ -153,10 +153,16 @@ public:
ret = OB_ENTRY_NOT_EXIST; ret = OB_ENTRY_NOT_EXIST;
} else { } else {
int64_t old_size = map_[key]; int64_t old_size = map_[key];
ret = this->log_block_mgr_.update_tenant(old_size, new_size); int64_t tmp_min_log_disk_size_for_all_tenants = this->log_block_mgr_.min_log_disk_size_for_all_tenants_;
tmp_min_log_disk_size_for_all_tenants -= old_size;
tmp_min_log_disk_size_for_all_tenants += new_size;
if (tmp_min_log_disk_size_for_all_tenants > this->log_block_mgr_.get_total_size_guarded_by_lock_()) {
ret = OB_MACHINE_RESOURCE_NOT_ENOUGH;
}
if (OB_SUCCESS != ret) { if (OB_SUCCESS != ret) {
map_[key] = old_size; map_[key] = old_size;
} else { } else {
this->log_block_mgr_.min_log_disk_size_for_all_tenants_ = tmp_min_log_disk_size_for_all_tenants;
map_[key] = new_size; map_[key] = new_size;
} }
} }