提交 c160d950 编写于 作者: J JiahuaChen 提交者: LINGuanRen

Fix pg_key not removed from tenant file pg_map when replaying 22x remove pg slog during upgrade

上级 e8339766
......@@ -77,9 +77,9 @@ public:
protected:
virtual int inner_add_partition(
ObIPartitionGroup& partition, const bool need_check_tenant, const bool is_replay, const bool allow_multi_value);
virtual int inner_del_partition_for_replay(const common::ObPartitionKey& pkey, const int64_t file_id);
virtual int inner_del_partition(const common::ObPartitionKey& pkey);
int inner_del_partition_impl(const common::ObPartitionKey& pkey, const int64_t* file_id);
int inner_del_partition_for_replay(const common::ObPartitionKey& pkey, const int64_t file_id);
int inner_del_partition(const common::ObPartitionKey& pkey);
virtual int inner_del_partition_impl(const common::ObPartitionKey& pkey, const int64_t* file_id);
virtual int init_partition_group(ObIPartitionGroup& pg, const common::ObPartitionKey& pkey);
virtual int post_replay_remove_pg_partition(const ObChangePartitionLogEntry& log_entry)
{
......
......@@ -3786,15 +3786,7 @@ int ObPartitionService::delete_rows(const transaction::ObTransDesc& trans_desc,
} else if (OB_FAIL(check_query_allowed(pkey, trans_desc, ctx_guard, guard))) {
STORAGE_LOG(WARN, "fail to check query allowed", K(ret));
} else {
//@NOTICE:(yuchen.wyc)为了规避外键自引用带来的防御检查不过的问题:
//由于目前delete语句的TableScan操作使用的快照点是语句级,无法看到本语句的最新修改,
//因此,对于外键自引用的级联删除时,同一行可能会被自己和外键级联操作多次删除,
//这个问题目前没有出现语义上的问题,但会导致delete的防御检查报错,详见:
// https://aone.alibaba-inc.com/issue/36022956
// DML的防御检查读使用的默认快照点是可以读到本语最新修改,因此对于该场景会出现两次读到的数据不一致的问题
//正确的做法是从外键的删除操作上规避掉多次删除同一行的情况,这要求delete的TableScan能够看到自己的最新修改
//由于担心这个修改的影响较大,3.2暂时从防御检查上规避掉这个问题,
// 4.0上delete改为读本语句的最新修改来避免同一行的多次删除
//@NOTICE:(yuchen.wyc) avoid defensive check problem on foreign key self reference
if (trans_desc.get_cur_stmt_desc().is_delete_stmt()) {
const_cast<ObDMLBaseParam &>(dml_param).query_flag_.read_latest_ = 0;
}
......@@ -3819,15 +3811,7 @@ int ObPartitionService::delete_row(const ObTransDesc& trans_desc, const ObDMLBas
} else if (OB_FAIL(check_query_allowed(pkey, trans_desc, ctx_guard, guard))) {
STORAGE_LOG(WARN, "fail to check query allowed", K(ret));
} else {
//@NOTICE:(yuchen.wyc)为了规避外键自引用带来的防御检查不过的问题:
//由于目前delete语句的TableScan操作使用的快照点是语句级,无法看到本语句的最新修改,
//因此,对于外键自引用的级联删除时,同一行可能会被自己和外键级联操作多次删除,
//这个问题目前没有出现语义上的问题,但会导致delete的防御检查报错,详见:
// https://aone.alibaba-inc.com/issue/36022956
// DML的防御检查读使用的默认快照点是可以读到本语最新修改,因此对于该场景会出现两次读到的数据不一致的问题
//正确的做法是从外键的删除操作上规避掉多次删除同一行的情况,这要求delete的TableScan能够看到自己的最新修改
//由于担心这个修改的影响较大,3.2暂时从防御检查上规避掉这个问题,
// 4.0上delete改为读本语句的最新修改来避免同一行的多次删除
//@NOTICE:(yuchen.wyc) avoid defensive check problem on foreign key self reference
if (trans_desc.get_cur_stmt_desc().is_delete_stmt()) {
const_cast<ObDMLBaseParam &>(dml_param).query_flag_.read_latest_ = 0;
}
......@@ -4271,32 +4255,6 @@ int ObPartitionService::inner_del_partition_impl(const ObPartitionKey& pkey, con
return ret;
}
int ObPartitionService::inner_del_partition(const ObPartitionKey& pkey)
{
int ret = OB_SUCCESS;
if (OB_FAIL(inner_del_partition_impl(pkey, nullptr /*file_id*/))) {
STORAGE_LOG(WARN, "fail to inner del partition", K(ret), K(pkey));
}
return ret;
}
int ObPartitionService::inner_del_partition_for_replay(const ObPartitionKey& pkey, const int64_t file_id)
{
int ret = OB_SUCCESS;
ObIPartitionGroupGuard guard;
if (OB_FAIL(get_partition(pkey, guard))) {
if (OB_PARTITION_NOT_EXIST == ret) {
LOG_INFO("pg not exist in partition image", K(pkey));
ret = OB_SUCCESS;
} else {
LOG_WARN("fail to get partition", K(ret), K(pkey));
}
} else if (OB_FAIL(inner_del_partition_impl(pkey, OB_INVALID_DATA_FILE_ID == file_id ? nullptr : &file_id))) {
STORAGE_LOG(WARN, "fail to inner del partition impl", K(ret));
}
return ret;
}
int ObPartitionService::init_partition_group(ObIPartitionGroup& pg, const common::ObPartitionKey& pkey)
{
int ret = OB_SUCCESS;
......
......@@ -991,9 +991,7 @@ private:
int remove_pg_from_mgr(const ObIPartitionGroup* partition, const bool write_slog);
int inner_add_partition(ObIPartitionGroup& partition, const bool need_check_tenant, const bool is_replay,
const bool allow_multi_value) override;
int inner_del_partition(const common::ObPartitionKey& pkey) override;
int inner_del_partition_for_replay(const common::ObPartitionKey& pkey, const int64_t file_id) override;
int inner_del_partition_impl(const common::ObPartitionKey& pkey, const int64_t* file_id);
int inner_del_partition_impl(const common::ObPartitionKey& pkey, const int64_t* file_id) override;
int create_sstables(const obrpc::ObCreatePartitionArg& arg, const bool in_slog_trans,
ObIPartitionGroup& partition_group, ObTablesHandle& handle);
int create_sstables(const ObCreatePartitionParam& arg, const bool in_slog_trans, ObIPartitionGroup& partition_group,
......
......@@ -171,6 +171,24 @@ int ObServerCheckpointWriter::update_tenant_file_super_block(
common::hash::ObHashMap<ObTenantFileKey, ObTenantFileCheckpointEntry>& file_checkpoint_map)
{
int ret = OB_SUCCESS;
// defensive code for trouble shooting
ObArenaAllocator allocator;
ObArray<ObTenantFileInfo *> tenant_file_infos;
if (OB_FAIL(OB_SERVER_FILE_MGR.get_all_tenant_file_infos(allocator, tenant_file_infos))) {
LOG_WARN("fail to get all tenant file infos", K(ret));
} else {
for (int64_t i = 0; i < tenant_file_infos.count(); ++i) {
const ObTenantFileInfo &file_info = *tenant_file_infos.at(i);
if (ObTenantFileStatus::TENANT_FILE_DELETING != file_info.tenant_file_super_block_.status_) {
ObTenantFileCheckpointEntry entry;
// ignore ret on purpose
if (OB_SUCCESS != file_checkpoint_map.get_refactored(file_info.tenant_key_, entry)) {
LOG_WARN("tenant file ckpt not updated, may be leak!", K(file_info));
}
}
}
}
for (common::hash::ObHashMap<ObTenantFileKey, ObTenantFileCheckpointEntry>::iterator iter =
file_checkpoint_map.begin();
OB_SUCC(ret) && iter != file_checkpoint_map.end();
......
......@@ -691,7 +691,7 @@ int ObTenantFileMgr::remove_pg(const ObTenantFileKey& file_key, const ObPGKey& p
} else {
if (file_value->file_info_.is_empty_file()) {
file_value->file_info_.tenant_file_super_block_.status_ = TENANT_FILE_DELETING;
LOG_INFO("mark file deleting", K(file_key));
FLOG_INFO("mark file deleting", K(file_key));
}
}
return ret;
......
......@@ -175,6 +175,8 @@ int ObTenantFileInfo::add_pg(const ObPGKey& pg_key)
if (OB_SUCC(ret)) {
if (OB_FAIL(pg_map_.set_refactored(pg_key, true))) {
LOG_WARN("fail to add pg to pg map", K(ret), K(pg_key));
} else {
FLOG_INFO("add pg", K(tenant_key_), K(pg_key));
}
}
return ret;
......@@ -190,6 +192,8 @@ int ObTenantFileInfo::remove_pg(const ObPGKey& pg_key)
ret = OB_ENTRY_NOT_EXIST;
} else if (OB_FAIL(pg_map_.erase_refactored(pg_key))) {
LOG_WARN("fail to erase pg from map", K(ret), K(pg_key));
} else {
FLOG_INFO("remove pg", K(tenant_key_), K(pg_key));
}
return ret;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册