From d384ead0f024995787b1f29bc672c33b0d3d40a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 2 Jan 2018 19:11:10 +0200 Subject: [PATCH] MDEV-14799 After UPDATE of indexed columns, old values will not be purged from secondary indexes This is a regression caused by MDEV-14051 'Undo log record is too big.' Purge in the secondary index is wrongly skipped in row_purge_upd_exist_or_extern() because node->row only does not contain all indexed columns. trx_undo_rec_get_partial_row(): Add the parameter for node->update so that the updated columns will be copied from the initial part of the undo log record. --- storage/innobase/include/trx0rec.h | 2 ++ storage/innobase/row/row0purge.c | 3 ++- storage/innobase/trx/trx0rec.c | 14 +++++++++++++- storage/xtradb/include/trx0rec.h | 2 ++ storage/xtradb/row/row0purge.c | 3 ++- storage/xtradb/trx/trx0rec.c | 14 +++++++++++++- 6 files changed, 34 insertions(+), 4 deletions(-) diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index a6e54d6dfd1..6e3233c685b 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -193,6 +194,7 @@ trx_undo_rec_get_partial_row( used, as we do NOT copy the data in the record! */ dict_index_t* index, /*!< in: clustered index */ + const upd_t* update, /*!< in: updated columns */ dtuple_t** row, /*!< out, own: partial row */ ibool ignore_prefix, /*!< in: flag to indicate if we expect blob prefixes in undo. Used diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c index 7b25612ba4b..f099eeb9aa9 100644 --- a/storage/innobase/row/row0purge.c +++ b/storage/innobase/row/row0purge.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -730,7 +731,7 @@ err_exit: if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { ptr = trx_undo_rec_get_partial_row( - ptr, clust_index, &node->row, + ptr, clust_index, node->update, &node->row, type == TRX_UNDO_UPD_DEL_REC, node->heap); } diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c index 94e22d688ca..19e934fc667 100644 --- a/storage/innobase/trx/trx0rec.c +++ b/storage/innobase/trx/trx0rec.c @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1072,6 +1072,7 @@ trx_undo_rec_get_partial_row( used, as we do NOT copy the data in the record! */ dict_index_t* index, /*!< in: clustered index */ + const upd_t* update, /*!< in: updated columns */ dtuple_t** row, /*!< out, own: partial row */ ibool ignore_prefix, /*!< in: flag to indicate if we expect blob prefixes in undo. Used @@ -1081,6 +1082,8 @@ trx_undo_rec_get_partial_row( { const byte* end_ptr; ulint row_len; + const upd_field_t* uf = update->fields; + const upd_field_t* const ue = update->fields + update->n_fields; ut_ad(index); ut_ad(ptr); @@ -1094,6 +1097,15 @@ trx_undo_rec_get_partial_row( dict_table_copy_types(*row, index->table); + + for (; uf != ue; uf++) { + ulint c = dict_index_get_nth_col(index, uf->field_no)->ind; + ut_ad(uf->orig_len == UNIV_SQL_NULL + || uf->orig_len < UNIV_EXTERN_STORAGE_FIELD); + ut_ad(!dfield_is_ext(&uf->new_val)); + *dtuple_get_nth_field(*row, c) = uf->new_val; + } + end_ptr = ptr + mach_read_from_2(ptr); ptr += 2; diff --git a/storage/xtradb/include/trx0rec.h b/storage/xtradb/include/trx0rec.h index a6e54d6dfd1..6e3233c685b 100644 --- a/storage/xtradb/include/trx0rec.h +++ b/storage/xtradb/include/trx0rec.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -193,6 +194,7 @@ trx_undo_rec_get_partial_row( used, as we do NOT copy the data in the record! */ dict_index_t* index, /*!< in: clustered index */ + const upd_t* update, /*!< in: updated columns */ dtuple_t** row, /*!< out, own: partial row */ ibool ignore_prefix, /*!< in: flag to indicate if we expect blob prefixes in undo. Used diff --git a/storage/xtradb/row/row0purge.c b/storage/xtradb/row/row0purge.c index 77d60edb71f..07ed57f55dd 100644 --- a/storage/xtradb/row/row0purge.c +++ b/storage/xtradb/row/row0purge.c @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -730,7 +731,7 @@ err_exit: if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { ptr = trx_undo_rec_get_partial_row( - ptr, clust_index, &node->row, + ptr, clust_index, node->update, &node->row, type == TRX_UNDO_UPD_DEL_REC, node->heap); } diff --git a/storage/xtradb/trx/trx0rec.c b/storage/xtradb/trx/trx0rec.c index f3f1d9a2d96..17d51ecf8d2 100644 --- a/storage/xtradb/trx/trx0rec.c +++ b/storage/xtradb/trx/trx0rec.c @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1085,6 +1085,7 @@ trx_undo_rec_get_partial_row( used, as we do NOT copy the data in the record! */ dict_index_t* index, /*!< in: clustered index */ + const upd_t* update, /*!< in: updated columns */ dtuple_t** row, /*!< out, own: partial row */ ibool ignore_prefix, /*!< in: flag to indicate if we expect blob prefixes in undo. Used @@ -1094,6 +1095,8 @@ trx_undo_rec_get_partial_row( { const byte* end_ptr; ulint row_len; + const upd_field_t* uf = update->fields; + const upd_field_t* const ue = update->fields + update->n_fields; ut_ad(index); ut_ad(ptr); @@ -1107,6 +1110,15 @@ trx_undo_rec_get_partial_row( dict_table_copy_types(*row, index->table); + + for (; uf != ue; uf++) { + ulint c = dict_index_get_nth_col(index, uf->field_no)->ind; + ut_ad(uf->orig_len == UNIV_SQL_NULL + || uf->orig_len < UNIV_EXTERN_STORAGE_FIELD); + ut_ad(!dfield_is_ext(&uf->new_val)); + *dtuple_get_nth_field(*row, c) = uf->new_val; + } + end_ptr = ptr + mach_read_from_2(ptr); ptr += 2;