Commit 4431144a authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-12353: Make UNDO_APPEND more robust

This is a follow-up to commit 84e3f9ce
that introduced the EXTENDED log record of UNDO_APPEND subtype.

mtr_t::undo_append(): Accurately enforce the mtr_buf_t::MAX_DATA_SIZE
limit. Also, replace mtr_buf_t::push() with simpler code, to append 1 byte
to the log.

log_phys_t::undo_append(): Return whether the page was found to
be in an inconsistent state.

log_phys_t::apply(): If corruption was noticed, stop applying log
unless innodb_force_recovery is set.
parent a346ff35
...@@ -615,7 +615,7 @@ inline void mtr_t::undo_append(const buf_block_t &block, ...@@ -615,7 +615,7 @@ inline void mtr_t::undo_append(const buf_block_t &block,
set_modified(); set_modified();
if (m_log_mode != MTR_LOG_ALL) if (m_log_mode != MTR_LOG_ALL)
return; return;
const bool small= len < mtr_buf_t::MAX_DATA_SIZE - (3 + 3 + 5 + 5); const bool small= len + 1 < mtr_buf_t::MAX_DATA_SIZE - (1 + 3 + 3 + 5 + 5);
byte *end= log_write<EXTENDED>(block.page.id, &block.page, len + 1, small); byte *end= log_write<EXTENDED>(block.page.id, &block.page, len + 1, small);
if (UNIV_LIKELY(small)) if (UNIV_LIKELY(small))
{ {
...@@ -626,8 +626,9 @@ inline void mtr_t::undo_append(const buf_block_t &block, ...@@ -626,8 +626,9 @@ inline void mtr_t::undo_append(const buf_block_t &block,
else else
{ {
m_log.close(end); m_log.close(end);
byte type= UNDO_APPEND; end= m_log.open(1);
m_log.push(&type, 1); *end++= UNDO_APPEND;
m_log.close(end);
m_log.push(static_cast<const byte*>(data), static_cast<uint32_t>(len)); m_log.push(static_cast<const byte*>(data), static_cast<uint32_t>(len));
} }
m_last_offset= FIL_PAGE_TYPE; m_last_offset= FIL_PAGE_TYPE;
......
...@@ -157,8 +157,9 @@ struct log_phys_t : public log_rec_t ...@@ -157,8 +157,9 @@ struct log_phys_t : public log_rec_t
@see mtr_t::undo_append() @see mtr_t::undo_append()
@param block undo log page @param block undo log page
@param data undo log record @param data undo log record
@param len length of the undo log record */ @param len length of the undo log record
static void undo_append(const buf_block_t &block, const byte *data, @return whether the operation failed (inconcistency was noticed) */
static bool undo_append(const buf_block_t &block, const byte *data,
size_t len) size_t len)
{ {
ut_ad(len > 2); ut_ad(len > 2);
...@@ -170,7 +171,7 @@ struct log_phys_t : public log_rec_t ...@@ -170,7 +171,7 @@ struct log_phys_t : public log_rec_t
{ {
ib::error() << "Not applying UNDO_APPEND due to corruption on " ib::error() << "Not applying UNDO_APPEND due to corruption on "
<< block.page.id; << block.page.id;
return; return true;
} }
byte *p= block.frame + free; byte *p= block.frame + free;
...@@ -180,6 +181,7 @@ struct log_phys_t : public log_rec_t ...@@ -180,6 +181,7 @@ struct log_phys_t : public log_rec_t
memcpy(p, data, len); memcpy(p, data, len);
p+= len; p+= len;
mach_write_to_2(p, free); mach_write_to_2(p, free);
return false;
} }
/** The status of apply() */ /** The status of apply() */
...@@ -307,7 +309,12 @@ struct log_phys_t : public log_rec_t ...@@ -307,7 +309,12 @@ struct log_phys_t : public log_rec_t
case UNDO_APPEND: case UNDO_APPEND:
if (UNIV_UNLIKELY(rlen <= 3)) if (UNIV_UNLIKELY(rlen <= 3))
goto record_corrupted; goto record_corrupted;
undo_append(block, ++l, --rlen); if (undo_append(block, ++l, --rlen) && !srv_force_recovery)
{
ib::error() << "Set innodb_force_recovery=1 to ignore corruption.";
recv_sys.found_corrupt_log= true;
return applied;
}
break; break;
case DELETE_ROW_FORMAT_REDUNDANT: case DELETE_ROW_FORMAT_REDUNDANT:
if (UNIV_UNLIKELY(rlen < 2 || rlen > 4)) if (UNIV_UNLIKELY(rlen < 2 || rlen > 4))
...@@ -2274,6 +2281,10 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr, ...@@ -2274,6 +2281,10 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
} }
set_start_lsn: set_start_lsn:
if (recv_sys.found_corrupt_log && !srv_force_recovery) {
break;
}
if (!start_lsn) { if (!start_lsn) {
start_lsn = l->start_lsn; start_lsn = l->start_lsn;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment