From 9eb3fcc9fbccfb13ad26e5d9faa0f70b580f291e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 3 Jan 2018 14:30:58 +0200 Subject: [PATCH] Follow-up fix of MDEV-14717 RENAME TABLE in InnoDB is not crash-safe trx_undo_page_report_rename(): Return a pointer to the start of the undo log record, not to the start of the (not yet written) next free record. The wrong return value would sometimes cause ROLLBACK to crash in an assertion failure (trying to parse garbage from the free area at the end of the insert_undo log page) if the TRX_UNDO_RENAME_TABLE record was the very last thing that was written to the insert_undo log. This would occasionally happen when an ALTER TABLE operation is rolled back due to invalid FOREIGN KEY constraints in the innodb.innodb test. In these tests, the error ER_ERROR_ON_RENAME (1025) would be returned at the end of the ALGORITHM=COPY operation of ALTER TABLE. --- storage/innobase/trx/trx0rec.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 0b04c5c4ea0..4ef63938e70 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1866,8 +1866,9 @@ ulint trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table, buf_block_t* block, mtr_t* mtr) { - ulint first_free = mach_read_from_2(block->frame + TRX_UNDO_PAGE_HDR - + TRX_UNDO_PAGE_FREE); + byte* ptr_first_free = TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE + + block->frame; + ulint first_free = mach_read_from_2(ptr_first_free); ut_ad(first_free >= TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE); ut_ad(first_free <= UNIV_PAGE_SIZE); byte* start = block->frame + first_free; @@ -1895,11 +1896,10 @@ trx_undo_page_report_rename(trx_t* trx, const dict_table_t* table, ptr += 2; ulint offset = page_offset(ptr); mach_write_to_2(start, offset); - mach_write_to_2(block->frame + TRX_UNDO_PAGE_HDR - + TRX_UNDO_PAGE_FREE, offset); + mach_write_to_2(ptr_first_free, offset); trx_undof_page_add_undo_rec_log(block->frame, first_free, offset, mtr); - return offset; + return first_free; } /** Report a RENAME TABLE operation.