From 462808f3b65b60958eaf8013b80857e341cc9f6c Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 20 Dec 2017 13:52:27 +0100 Subject: [PATCH 1/6] MDEV-10657: incorrect result returned with binary protocol (prepared statements) If translation table present when we materialize the derived table then change it to point to the materialized table. Added debug info to see really what happens with what derived. --- mysql-test/r/ps.result | 18 ++++++++++++++++ mysql-test/t/ps.test | 15 +++++++++++++ sql/sql_class.cc | 9 +++++++- sql/sql_derived.cc | 48 ++++++++++++++++++++++++++++++++++++++++-- sql/table.cc | 3 +++ sql/table.h | 6 ++++++ 6 files changed, 96 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 3fed0a5b0d1..209d3d85108 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -4316,4 +4316,22 @@ set join_cache_level=@join_cache_level_save; deallocate prepare stmt; drop view v1,v2,v3; drop table t1,t2,t3; +# +# MDEV-10657: incorrect result returned with binary protocol +# (prepared statements) +# +create table t1 (code varchar(10) primary key); +INSERT INTO t1(code) VALUES ('LINE1'), ('LINE2'), ('LINE3'); +SELECT X.* +FROM +(SELECT CODE, RN +FROM +(SELECT A.CODE, @cnt := @cnt + 1 AS RN +FROM t1 A, (SELECT @cnt := 0) C) T +) X; +CODE RN +LINE1 1 +LINE2 2 +LINE3 3 +drop table t1; # End of 5.5 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 4431f722ae0..ea67e1074f9 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3843,4 +3843,19 @@ deallocate prepare stmt; drop view v1,v2,v3; drop table t1,t2,t3; +--echo # +--echo # MDEV-10657: incorrect result returned with binary protocol +--echo # (prepared statements) +--echo # + +create table t1 (code varchar(10) primary key); +INSERT INTO t1(code) VALUES ('LINE1'), ('LINE2'), ('LINE3'); +SELECT X.* +FROM + (SELECT CODE, RN + FROM + (SELECT A.CODE, @cnt := @cnt + 1 AS RN + FROM t1 A, (SELECT @cnt := 0) C) T + ) X; +drop table t1; --echo # End of 5.5 tests diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 00d860e7887..b007729494e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2192,6 +2192,8 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, MEM_ROOT *runtime_memroot) { Item_change_record *change; + DBUG_ENTER("THD::nocheck_register_item_tree_change"); + DBUG_PRINT("enter", ("Register %p <- %p", old_value, (*place))); /* Now we use one node per change, which adds some memory overhead, but still is rather fast as we use alloc_root for allocations. @@ -2204,12 +2206,13 @@ void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, OOM, thd->fatal_error() is called by the error handler of the memroot. Just return. */ - return; + DBUG_VOID_RETURN; } change= new (change_mem) Item_change_record; change->place= place; change->old_value= old_value; change_list.append(change); + DBUG_VOID_RETURN; } /** @@ -2250,7 +2253,11 @@ void THD::rollback_item_tree_changes() DBUG_ENTER("rollback_item_tree_changes"); while ((change= it++)) + { + DBUG_PRINT("info", ("revert %p -> %p", + change->old_value, (*change->place))); *change->place= change->old_value; + } /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); DBUG_VOID_RETURN; diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 6cd4547aaf9..2a6d82c161a 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -361,6 +361,9 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX *parent_lex= derived->select_lex; Query_arena *arena, backup; DBUG_ENTER("mysql_derived_merge"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); if (derived->merged) DBUG_RETURN(FALSE); @@ -508,6 +511,9 @@ unconditional_materialization: bool mysql_derived_merge_for_insert(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_merge_for_insert"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); if (derived->merged_for_insert) DBUG_RETURN(FALSE); if (derived->init_derived(thd, FALSE)) @@ -554,6 +560,9 @@ bool mysql_derived_init(THD *thd, LEX *lex, TABLE_LIST *derived) { SELECT_LEX_UNIT *unit= derived->get_unit(); DBUG_ENTER("mysql_derived_init"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); // Skip already prepared views/DT if (!unit || unit->prepared) @@ -624,7 +633,9 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) SELECT_LEX_UNIT *unit= derived->get_unit(); DBUG_ENTER("mysql_derived_prepare"); bool res= FALSE; - DBUG_PRINT("enter", ("unit 0x%lx", (ulong) unit)); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); // Skip already prepared views/DT if (!unit || unit->prepared || @@ -781,6 +792,9 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) bool res= FALSE; DBUG_ENTER("mysql_derived_optimize"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); if (unit->optimized) DBUG_RETURN(FALSE); @@ -846,6 +860,9 @@ err: bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_create"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); TABLE *table= derived->table; SELECT_LEX_UNIT *unit= derived->get_unit(); @@ -895,9 +912,13 @@ bool mysql_derived_create(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) { - DBUG_ENTER("mysql_derived_fill"); + Field_iterator_table field_iterator; SELECT_LEX_UNIT *unit= derived->get_unit(); bool res= FALSE; + DBUG_ENTER("mysql_derived_fill"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); if (unit->executed && !unit->uncacheable && !unit->describe) DBUG_RETURN(FALSE); @@ -937,7 +958,27 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) if (derived_result->flush()) res= TRUE; unit->executed= TRUE; + + if (derived->field_translation) + { + /* reset translation table to materialized table */ + field_iterator.set_table(derived->table); + for (uint i= 0; + !field_iterator.end_of_fields(); + field_iterator.next(), i= i + 1) + { + Item *item; + + if (!(item= field_iterator.create_item(thd))) + { + res= TRUE; + break; + } + thd->change_item_tree(&derived->field_translation[i].item, item); + } + } } + if (res || !lex->describe) unit->cleanup(); lex->current_select= save_current_select; @@ -966,6 +1007,9 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) { DBUG_ENTER("mysql_derived_reinit"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (derived->alias ? derived->alias : ""), + derived->get_unit())); st_select_lex_unit *unit= derived->get_unit(); if (derived->table) diff --git a/sql/table.cc b/sql/table.cc index fbcd91f5326..9cade76cb78 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4108,6 +4108,9 @@ bool TABLE_LIST::create_field_translation(THD *thd) Query_arena *arena, backup; bool res= FALSE; DBUG_ENTER("TABLE_LIST::create_field_translation"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : ""), + get_unit())); if (thd->stmt_arena->is_conventional() || thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) diff --git a/sql/table.h b/sql/table.h index c981243f28c..98f8c7ad73f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -2107,6 +2107,9 @@ struct TABLE_LIST inline void set_merged_derived() { DBUG_ENTER("set_merged_derived"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : ""), + get_unit())); derived_type= ((derived_type & DTYPE_MASK) | DTYPE_TABLE | DTYPE_MERGE); set_check_merged(); @@ -2119,6 +2122,9 @@ struct TABLE_LIST void set_materialized_derived() { DBUG_ENTER("set_materialized_derived"); + DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", + (alias ? alias : ""), + get_unit())); derived_type= ((derived_type & (derived ? DTYPE_MASK : DTYPE_VIEW)) | DTYPE_TABLE | DTYPE_MATERIALIZE); set_check_materialized(); From 1300627a5dcffdb005e2c31e0ba88f47fa519742 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 27 Dec 2017 22:10:17 +0100 Subject: [PATCH 2/6] MDEV-14309 MTR tests require perl-Env which is not always in the default installation * don't use Env module in tests, use $ENV{xxx} instead * collateral changes: ** $file in the error message was unset ** $file in the other error message was unset too :) ** source file arguments are conventionally upper-cased ** abort the test (die) on error, don't just echo/exit --- mysql-test/include/truncate_file.inc | 11 +++-------- .../suite/rpl/t/rpl_manual_change_index_file.test | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/mysql-test/include/truncate_file.inc b/mysql-test/include/truncate_file.inc index 2326d6c0b94..fe88cb05bd9 100644 --- a/mysql-test/include/truncate_file.inc +++ b/mysql-test/include/truncate_file.inc @@ -1,16 +1,11 @@ # truncate a giving file, all contents of the file are be cleared -if (!$file) +if (!$TRUNCATE_FILE) { - --echo Please assign a file name to $file!! - exit; + die TRUNCATE_FILE is not set; } -let TRUNCATE_FILE= $file; - perl; -use Env; -Env::import('TRUNCATE_FILE'); -open FILE, '>', $TRUNCATE_FILE || die "Can not open file $file"; +open FILE, '>', $ENV{TRUNCATE_FILE} or die "open(>$ENV{TRUNCATE_FILE}): $!"; close FILE; EOF diff --git a/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test index 981cecb66ad..1c087c550d0 100644 --- a/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test +++ b/mysql-test/suite/rpl/t/rpl_manual_change_index_file.test @@ -25,7 +25,7 @@ sync_slave_with_master; connection master; # Delete './master-bin.000001' from index file. let $MYSQLD_DATADIR= `SELECT @@DATADIR`; -let $file= $MYSQLD_DATADIR/master-bin.index; +let TRUNCATE_FILE= $MYSQLD_DATADIR/master-bin.index; source include/truncate_file.inc; if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`) From eef2bc5a5c30eef43eee035e23b87286a8dd50bd Mon Sep 17 00:00:00 2001 From: Ian Gilfillan Date: Thu, 28 Dec 2017 17:13:42 +0200 Subject: [PATCH 3/6] Update mysqladmin man page --- man/mysqladmin.1 | 186 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 2 deletions(-) diff --git a/man/mysqladmin.1 b/man/mysqladmin.1 index 65f348cab0c..0d71644e748 100644 --- a/man/mysqladmin.1 +++ b/man/mysqladmin.1 @@ -1,6 +1,6 @@ '\" t .\" -.TH "\FBMYSQLADMIN\FR" "1" "04/08/2015" "MariaDB 10\&.0" "MariaDB Database System" +.TH "\FBMYSQLADMIN\FR" "1" "28 December 2017" "MariaDB 10\&.0" "MariaDB Database System" .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- @@ -106,6 +106,97 @@ Display the server status variables and their values\&. .sp -1 .IP \(bu 2.3 .\} +flush\-all\-statistics +.sp +Flush all statistics tables\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +flush\-all\-status +.sp +Flush all status and statistics\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +flush\-binary\-log +.sp +Flush the binary log\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +flush\-client\-statistics +.sp +Flush client statistics\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +flush\-engine\-log +.sp +Flush engine log\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +flush\-error\-log +.sp +Flush error log\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +flush\-general\-log +.sp +Flush general query log\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} flush\-hosts .sp Flush all information in the host cache\&. @@ -119,6 +210,19 @@ Flush all information in the host cache\&. .sp -1 .IP \(bu 2.3 .\} +flush\-index\-statistics +.sp +Flush index statistics\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} flush\-logs .sp Flush all logs\&. @@ -146,6 +250,32 @@ reload)\&. .sp -1 .IP \(bu 2.3 .\} +flush\-relay\-log +.sp +Flush relay log\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} +flush\-slow\-log +.sp +Flush slow query log\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} flush\-status .sp Clear status variables\&. @@ -159,6 +289,19 @@ Clear status variables\&. .sp -1 .IP \(bu 2.3 .\} +flush\-table\-statistics +.sp +Flush table statistics\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} flush\-tables .sp Flush all tables\&. @@ -185,6 +328,19 @@ Flush the thread cache\&. .sp -1 .IP \(bu 2.3 .\} +flush\-user\-resources +.sp +Flush user resources\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} kill \fIid\fR,\fIid\fR,\&.\&.\&. .sp Kill server threads\&. If multiple thread ID values are given, there must be no spaces in the list\&. @@ -344,6 +500,19 @@ Stop the server\&. .sp -1 .IP \(bu 2.3 .\} +start\-all\-slaves +.sp +Start all slaves\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} start\-slave .sp Start replication on a slave server\&. @@ -370,6 +539,19 @@ Display a short server status message\&. .sp -1 .IP \(bu 2.3 .\} +stop\-all\-slaves +.sp +Stop all slaves\&. +.RE +.sp +.RS 4 +.ie n \{\ +\h'-04'\(bu\h'+03'\c +.\} +.el \{\ +.sp -1 +.IP \(bu 2.3 +.\} stop\-slave .sp Stop replication on a slave server\&. @@ -821,7 +1003,7 @@ Connect to the MariaDB server on the given host\&. \fB\-\-local\fR, \fB\-l\fR .sp -Suppress the SQL command(s) from being written to the binary log by enabled sql_log_bin=0 for the session\&. +Suppress the SQL command(s) from being written to the binary log by using FLUSH LOCAL or enabling sql_log_bin=0 for the session\&. .RE .sp .RS 4 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 4/6] 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; From 20fab71b144f85be9e2ccc145d24d257b0e9df7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 2 Jan 2018 21:41:39 +0200 Subject: [PATCH 5/6] Follow-up to MDEV-14799: Remove bogus debug assertions trx_undo_rec_get_partial_row(): When the PRIMARY KEY includes a column prefix of an externally stored column, the already parsed part of the undo log record may contain a reference to an off-page column. This is the case in the bug58912 test in innodb.innodb. --- storage/innobase/trx/trx0rec.c | 3 --- storage/xtradb/trx/trx0rec.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c index 19e934fc667..aba5e707c4f 100644 --- a/storage/innobase/trx/trx0rec.c +++ b/storage/innobase/trx/trx0rec.c @@ -1100,9 +1100,6 @@ trx_undo_rec_get_partial_row( 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; } diff --git a/storage/xtradb/trx/trx0rec.c b/storage/xtradb/trx/trx0rec.c index 17d51ecf8d2..167e6b356d3 100644 --- a/storage/xtradb/trx/trx0rec.c +++ b/storage/xtradb/trx/trx0rec.c @@ -1113,9 +1113,6 @@ trx_undo_rec_get_partial_row( 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; } From 7a9fee9853c19c1d6d547cd17f87e9bd8f4ebbaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 2 Jan 2018 09:25:37 +0200 Subject: [PATCH 6/6] MDEV-13568 gcol.innodb_virtual_debug_purge failed in buildbot with wrong result The InnoDB background tasks can modify tables while LOCK TABLES...WRITE is in effect. The purge of InnoDB history always worked like this in MariaDB, but in MySQL 5.7 it sometimes yields to LOCK TABLES. Also, make gcol.innodb_virtual_index run the purge for an UPDATE before DROP TABLE is executed. --- mysql-test/suite/gcol/disabled.def | 1 - .../suite/gcol/r/innodb_virtual_debug_purge.result | 11 +++-------- mysql-test/suite/gcol/r/innodb_virtual_index.result | 4 ++++ .../suite/gcol/t/innodb_virtual_debug_purge.test | 7 +++---- mysql-test/suite/gcol/t/innodb_virtual_index.test | 6 ++++++ mysql-test/unstable-tests | 3 ++- 6 files changed, 18 insertions(+), 14 deletions(-) delete mode 100644 mysql-test/suite/gcol/disabled.def diff --git a/mysql-test/suite/gcol/disabled.def b/mysql-test/suite/gcol/disabled.def deleted file mode 100644 index 37209a4c353..00000000000 --- a/mysql-test/suite/gcol/disabled.def +++ /dev/null @@ -1 +0,0 @@ -innodb_virtual_debug_purge : MDEV-13568 should purge yield to LOCK TABLES? diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result index 7d1d1d30198..ac4be0dcc6c 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result @@ -143,20 +143,15 @@ connect prevent_purge, localhost, root; start transaction with consistent snapshot; connection default; update t set a = repeat('m', 16000) where a like "aaa%"; -connect con1, localhost, root; +connect lock_table, localhost, root; lock table t write; disconnect prevent_purge; connection default; -select variable_value>1 from information_schema.global_status where variable_name='innodb_purge_trx_id_age'; -variable_value>1 -1 -disconnect con1; +InnoDB 0 transactions not purged +disconnect lock_table; start transaction with consistent snapshot; commit; InnoDB 0 transactions not purged -select variable_value>1 from information_schema.global_status where variable_name='innodb_purge_trx_id_age'; -variable_value>1 -0 set global debug_dbug=@old_dbug; drop table t; set debug_sync=reset; diff --git a/mysql-test/suite/gcol/r/innodb_virtual_index.result b/mysql-test/suite/gcol/r/innodb_virtual_index.result index 375c62bd173..b1f7976c6c0 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_index.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_index.result @@ -1,3 +1,5 @@ +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # Bug 21922176 - PREBUILT->SEARCH_TUPLE CREATED WITHOUT INCLUDING # THE NUMBER OF VIRTUAL COLUMNS @@ -86,6 +88,7 @@ DISTINCT I1.c14 AS y FROM t1 AS I1 ORDER BY I1.c14); SET @@SESSION.sql_mode=default; +InnoDB 0 transactions not purged DROP TABLE t1, t2, t3; # # Bug 22650296 - ASSERTION IN INNOBASE_BUILD_COL_MAP, ALTER @@ -194,3 +197,4 @@ ALTER TABLE t1 ADD COLUMN col7a INT GENERATED ALWAYS AS (col1 % col2) VIRTUAL, ADD UNIQUE index idx (col1), algorithm=inplace; ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: INPLACE ADD or DROP of virtual columns cannot be combined with other ALTER TABLE actions. Try ALGORITHM=COPY DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test index 2668e26c976..1862de268af 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test @@ -182,16 +182,15 @@ connect(prevent_purge, localhost, root); start transaction with consistent snapshot; connection default; update t set a = repeat('m', 16000) where a like "aaa%"; -connect(con1, localhost, root); +connect(lock_table, localhost, root); lock table t write; disconnect prevent_purge; connection default; -select variable_value>1 from information_schema.global_status where variable_name='innodb_purge_trx_id_age'; -disconnect con1; +--source ../../innodb/include/wait_all_purged.inc +disconnect lock_table; start transaction with consistent snapshot; commit; --source ../../innodb/include/wait_all_purged.inc -select variable_value>1 from information_schema.global_status where variable_name='innodb_purge_trx_id_age'; set global debug_dbug=@old_dbug; drop table t; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_index.test b/mysql-test/suite/gcol/t/innodb_virtual_index.test index 4c4cb2a2d05..432faeb65ae 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_index.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_index.test @@ -1,5 +1,9 @@ --source include/have_innodb.inc +# Ensure that the history list length will actually be decremented by purge. +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; + --echo # --echo # Bug 21922176 - PREBUILT->SEARCH_TUPLE CREATED WITHOUT INCLUDING --echo # THE NUMBER OF VIRTUAL COLUMNS @@ -96,6 +100,7 @@ FROM t1 AS I1 ORDER BY I1.c14); SET @@SESSION.sql_mode=default; +--source ../../innodb/include/wait_all_purged.inc DROP TABLE t1, t2, t3; @@ -218,3 +223,4 @@ ALTER TABLE t1 ADD COLUMN col7a INT GENERATED ALWAYS AS (col1 % col2) VIRTUAL, ADD UNIQUE index idx (col1), algorithm=inplace; DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index dff89fdf60d..4940faa944a 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -168,7 +168,8 @@ galera_3nodes.* : Suite is not stable yet gcol.innodb_virtual_basic : Modified in 10.2.11 gcol.innodb_virtual_debug : Modified in 10.2.11 -gcol.innodb_virtual_debug_purge : MDEV-13568 - Wrong result +gcol.innodb_virtual_debug_purge : Modified in 10.2.12 +gcol.innodb_virtual_index : Modified in 10.2.12 gcol.innodb_virtual_rebuild : Added in 10.2.11 gcol.innodb_virtual_stats : Added in 10.2.12