[CP] fix round checkpoint scn is not consistent with piece checkpoint scn

This commit is contained in:
wxhwang
2024-04-28 06:18:16 +00:00
committed by ob-robot
parent 57b9848525
commit ead3e7cb36
3 changed files with 344 additions and 8 deletions

View File

@ -100,7 +100,7 @@ int ObDestRoundCheckpointer::checkpoint(const ObTenantArchiveRoundAttr &round_in
LOG_WARN("backwards, checkpoint scn is bigger than limit scn", K(ret), K(round_info), K_(max_checkpoint_scn));
} else if (OB_FAIL(count_(round_info, summary, counter))) {
LOG_WARN("failed to to count", K(ret), K(round_info), K(summary));
} else if (OB_FAIL(gen_new_round_info_(round_info, counter, result.new_round_info_, need_checkpoint))) {
} else if (OB_FAIL(gen_new_round_info_(round_info, summary, counter, result.new_round_info_, need_checkpoint))) {
LOG_WARN("failed to decide next state", K(ret), K(round_info), K(counter), K(summary));
} else if (!need_checkpoint) {
} else if (OB_FAIL(checkpoint_(round_info, summary, result))) {
@ -177,8 +177,81 @@ int ObDestRoundCheckpointer::count_(
return ret;
}
int ObDestRoundCheckpointer::gen_new_round_info_(const ObTenantArchiveRoundAttr &old_round_info, const ObDestRoundCheckpointer::Counter &counter,
ObTenantArchiveRoundAttr &new_round_info, bool &need_checkpoint) const
int ObDestRoundCheckpointer::calc_next_checkpoint_scn_(
const ObTenantArchiveRoundAttr &old_round_info,
const ObDestRoundSummary &summary,
const Counter &counter,
SCN &next_checkpoint_scn) const
{
int ret = OB_SUCCESS;
SCN max_avail_piece_start_scn;
SCN max_avail_piece_checkpoint_scn;
int64_t max_avail_piece_id = 0;
// The next checkpoint scn can not exceed the max_checkpoint_scn_ which takes the GTS.
next_checkpoint_scn = MIN(max_checkpoint_scn_, counter.checkpoint_scn_);
if (OB_FAIL(ObTenantArchiveMgr::decide_piece_id(
old_round_info.start_scn_,
old_round_info.base_piece_id_,
old_round_info.piece_switch_interval_,
next_checkpoint_scn,
max_avail_piece_id))) {
LOG_WARN("failed to calc max available piece id", K(ret), K(old_round_info), K(next_checkpoint_scn));
} else if (OB_FAIL(ObTenantArchiveMgr::decide_piece_start_scn(
old_round_info.start_scn_,
old_round_info.base_piece_id_,
old_round_info.piece_switch_interval_,
max_avail_piece_id,
max_avail_piece_start_scn))) {
LOG_WARN("failed to calc max available piece start scn", K(ret), K(old_round_info), K(max_avail_piece_id));
}
// Consider 2 log streams, the log groups info are as following :
// 1001: [500, 600], [700, 1200]
// 1002: [500, 900]
// Then the reasonable next round checkpoint scn is 900. However, suppose the piece switch end scn is 1000,
// if we specify to restore until 800, the result is that it will return and cannot be recovered. As the
// log with range [700, 800] is in next piece, but the file status is BACKUP_FILE_INCOMPLETE which we will
// ignore during restore. In this case, the next round checkpoint scn will be adjust to 600, instead of 900.
max_avail_piece_checkpoint_scn = SCN::max_scn();
const ObArray<ObLSDestRoundSummary> &ls_round_list = summary.ls_round_list_;
for (int64_t i = 0; OB_SUCC(ret) && i < ls_round_list.count(); i++) {
const ObLSDestRoundSummary &ls_round = ls_round_list.at(i);
// search the piece
int64_t idx = ls_round.get_piece_idx(max_avail_piece_id);
if (-1 == idx) {
LOG_INFO("ls piece not found", K(ret), K(max_avail_piece_id), K(ls_round));
} else {
bool last_piece = false;
const ObLSDestRoundSummary::OnePiece &ls_piece = ls_round.piece_list_.at(idx);
if (OB_FAIL(ls_round.check_is_last_piece_for_deleted_ls(max_avail_piece_id, last_piece))) {
LOG_WARN("failed to check is last piece for deleted ls", K(ret));
} else if (last_piece) {
// If the ls is deleted, and this is the last piece. It should not
// affect the checkpoint_scn.
// Mark the last piece deleted for deleted ls. For example, piece 10 and 11 is found of
// a deleted ls for current checkpoint, piece 10 is not marked with deleted, but piece 11
// is marked with deleted.
// do nothing.
} else {
// checkpoint scn may be smaller than start scn for empty piece.
max_avail_piece_checkpoint_scn = MAX(max_avail_piece_start_scn, MIN(max_avail_piece_checkpoint_scn, ls_piece.checkpoint_scn_));
}
}
}
if (OB_SUCC(ret)) {
next_checkpoint_scn = MIN(next_checkpoint_scn, max_avail_piece_checkpoint_scn);
}
return ret;
}
int ObDestRoundCheckpointer::gen_new_round_info_(
const ObTenantArchiveRoundAttr &old_round_info,
const ObDestRoundSummary &summary,
const ObDestRoundCheckpointer::Counter &counter,
ObTenantArchiveRoundAttr &new_round_info,
bool &need_checkpoint) const
{
int ret = OB_SUCCESS;
// Current existing log stream count.
@ -193,11 +266,11 @@ int ObDestRoundCheckpointer::gen_new_round_info_(const ObTenantArchiveRoundAttr
old_round_info.piece_switch_interval_, counter.max_scn_, new_round_info.used_piece_id_))) {
LOG_WARN("failed to calc MAX piece id", K(ret), K(old_round_info), K(counter));
} else if (OB_FALSE_IT(new_round_info.max_scn_ = counter.max_scn_)) {
} else if (OB_FALSE_IT(next_checkpoint_scn = MIN(max_checkpoint_scn_, counter.checkpoint_scn_))) {
// Checkpoint can not over limit ts. However, if old round goes into STOPPING, then we will not
// move checkpoint_scn on.
} else if (OB_FAIL(calc_next_checkpoint_scn_(old_round_info, summary, counter, next_checkpoint_scn))) {
LOG_WARN("failed to calc next checkpoint scn", K(ret), K(old_round_info), K(summary), K(counter));
}
if (OB_FAIL(ret)) {
} else if (old_round_info.state_.is_beginning()) {
if (counter.not_start_cnt_ > 0) {

View File

@ -106,8 +106,17 @@ private:
bool can_do_checkpoint_(const ObTenantArchiveRoundAttr &round_info) const;
int count_(const ObTenantArchiveRoundAttr &old_round_info, const ObDestRoundSummary &summary, Counter &counter) const;
int gen_new_round_info_(const ObTenantArchiveRoundAttr &old_round_info, const Counter &counter,
ObTenantArchiveRoundAttr &new_round_info, bool &need_checkpoint) const;
int calc_next_checkpoint_scn_(
const ObTenantArchiveRoundAttr &old_round_info,
const ObDestRoundSummary &summary,
const Counter &counter,
SCN &next_checkpoint_scn) const;
int gen_new_round_info_(
const ObTenantArchiveRoundAttr &old_round_info,
const ObDestRoundSummary &summary,
const Counter &counter,
ObTenantArchiveRoundAttr &new_round_info,
bool &need_checkpoint) const;
// do checkpoint to checkpoint_ts.
int checkpoint_(const ObTenantArchiveRoundAttr &round_info, const ObDestRoundSummary &summary,