diff --git a/mysql-test/suite/innodb/r/undo_log.result b/mysql-test/suite/innodb/r/undo_log.result new file mode 100644 index 00000000000..a40c6b5b3bf --- /dev/null +++ b/mysql-test/suite/innodb/r/undo_log.result @@ -0,0 +1,142 @@ +CREATE TABLE test_tab ( +a_str_18 mediumtext, +b_str_3 varchar(32) DEFAULT NULL, +a_str_13 mediumtext, +b_str_5 varchar(40) DEFAULT NULL, +b_str_6 varchar(50) DEFAULT NULL, +b_str_7 char(32) DEFAULT NULL, +b_str_8 varchar(32) DEFAULT NULL, +b_str_9 varchar(255) DEFAULT NULL, +a_str_28 char(255) DEFAULT NULL, +a_str_27 varchar(255) DEFAULT NULL, +b_str_10 varchar(32) DEFAULT NULL, +a_str_26 varchar(255) DEFAULT NULL, +a_str_6 varchar(50) DEFAULT NULL, +b_str_11 varchar(32) DEFAULT NULL, +b_str_12 varchar(255) DEFAULT NULL, +b_str_13 char(32) DEFAULT NULL, +b_str_14 varchar(32) DEFAULT NULL, +b_str_15 char(32) DEFAULT NULL, +b_str_16 char(32) DEFAULT NULL, +b_str_17 varchar(32) DEFAULT NULL, +b_str_18 varchar(32) DEFAULT NULL, +a_str_25 varchar(40) DEFAULT NULL, +b_str_19 varchar(255) DEFAULT NULL, +a_str_23 varchar(40) DEFAULT NULL, +b_str_20 varchar(32) DEFAULT NULL, +a_str_21 varchar(255) DEFAULT NULL, +a_str_20 varchar(255) DEFAULT NULL, +a_str_39 varchar(255) DEFAULT NULL, +a_str_38 varchar(255) DEFAULT NULL, +a_str_37 varchar(255) DEFAULT NULL, +b_str_21 char(32) DEFAULT NULL, +b_str_23 varchar(80) DEFAULT NULL, +b_str_24 varchar(32) DEFAULT NULL, +b_str_25 varchar(32) DEFAULT NULL, +b_str_26 char(32) NOT NULL DEFAULT '', +b_str_27 varchar(255) DEFAULT NULL, +a_str_36 varchar(255) DEFAULT NULL, +a_str_33 varchar(100) DEFAULT NULL, +a_ref_10 char(32) DEFAULT NULL, +b_str_28 char(32) DEFAULT NULL, +b_str_29 char(32) DEFAULT NULL, +a_ref_6 char(32) DEFAULT NULL, +a_ref_12 varchar(32) DEFAULT NULL, +a_ref_11 varchar(32) DEFAULT NULL, +a_str_49 varchar(40) DEFAULT NULL, +b_str_30 varchar(32) DEFAULT NULL, +a_ref_3 varchar(32) DEFAULT NULL, +a_str_48 varchar(40) DEFAULT NULL, +a_ref_1 char(32) DEFAULT NULL, +b_str_31 varchar(32) DEFAULT NULL, +b_str_32 varchar(255) DEFAULT NULL, +b_str_33 char(32) DEFAULT NULL, +b_str_34 varchar(32) DEFAULT NULL, +a_str_47 varchar(40) DEFAULT NULL, +b_str_36 varchar(255) DEFAULT NULL, +a_str_46 varchar(40) DEFAULT NULL, +a_str_45 varchar(255) DEFAULT NULL, +b_str_38 varchar(32) DEFAULT NULL, +b_str_39 char(32) DEFAULT NULL, +b_str_40 varchar(32) DEFAULT NULL, +a_str_41 varchar(255) DEFAULT NULL, +b_str_41 varchar(32) DEFAULT NULL, +PRIMARY KEY (b_str_26), +UNIQUE KEY a_str_47 (a_str_47), +UNIQUE KEY a_str_49 (a_str_49), +UNIQUE KEY a_str_33 (a_str_33), +UNIQUE KEY a_str_46 (a_str_46), +UNIQUE KEY a_str_48 (a_str_48), +KEY b_str_18 (b_str_18), +KEY a_str_26 (a_str_26), +KEY b_str_27 (b_str_27,b_str_19), +KEY b_str_41 (b_str_41), +KEY b_str_15 (b_str_15), +KEY a_str_20 (a_str_20), +KEY b_str_17 (b_str_17), +KEY b_str_40 (b_str_40), +KEY b_str_24 (b_str_24), +KEY b_str_10 (b_str_10), +KEY b_str_16 (b_str_16), +KEY b_str_29 (b_str_29), +KEY a_str_41 (a_str_41), +KEY b_str_7 (b_str_7), +KEY a_str_45 (a_str_45), +KEY a_str_28 (a_str_28), +KEY a_str_37 (a_str_37), +KEY b_str_6 (b_str_6), +KEY a_ref_6 (a_ref_6), +KEY b_str_34 (b_str_34), +KEY b_str_38 (b_str_38), +KEY a_ref_10 (a_ref_10), +KEY b_str_21 (b_str_21), +KEY b_str_23 (b_str_23,b_str_19), +KEY b_str_33 (b_str_33), +KEY a_ref_12 (a_ref_12), +KEY a_str_18 (a_str_18(255)), +KEY a_str_39 (a_str_39), +KEY a_str_27 (a_str_27), +KEY a_str_25 (a_str_25), +KEY b_str_9 (b_str_9), +KEY a_str_23 (a_str_23), +KEY b_str_8 (b_str_8), +KEY a_str_21 (a_str_21), +KEY b_str_3 (b_str_3), +KEY b_str_30 (b_str_30), +KEY b_str_12 (b_str_12), +KEY b_str_25 (b_str_25), +KEY b_str_13 (b_str_13), +KEY a_str_38 (a_str_38), +KEY a_str_13 (a_str_13(255)), +KEY a_str_36 (a_str_36), +KEY b_str_28 (b_str_28), +KEY b_str_19 (b_str_19), +KEY b_str_11 (b_str_11), +KEY a_ref_1 (a_ref_1), +KEY b_str_20 (b_str_20), +KEY b_str_14 (b_str_14), +KEY a_ref_3 (a_ref_3), +KEY b_str_39 (b_str_39), +KEY b_str_32 (b_str_32), +KEY a_str_6 (a_str_6), +KEY b_str_5 (b_str_5), +KEY b_str_31 (b_str_31), +KEY a_ref_11 (a_ref_11) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; +BEGIN; +INSERT INTO test_tab (b_str_26, a_str_13, a_str_18) VALUES +('a', REPEAT('f',4031), REPEAT('g', 4031)); +UPDATE test_tab SET a_str_13=REPEAT('h',4032), a_str_18=REPEAT('i',4032); +SELECT 'Reducing length to 4030'; +Reducing length to 4030 +Reducing length to 4030 +UPDATE test_tab SET a_str_13=REPEAT('j',4030), a_str_18=REPEAT('k',4030); +UPDATE test_tab SET a_str_13=REPEAT('l',4031), a_str_18=REPEAT('m',4031); +ROLLBACK; +SELECT COUNT(*) FROM test_tab; +COUNT(*) +0 +CHECK TABLE test_tab; +Table Op Msg_type Msg_text +test.test_tab check status OK +DROP TABLE test_tab; diff --git a/mysql-test/suite/innodb/t/undo_log.test b/mysql-test/suite/innodb/t/undo_log.test new file mode 100644 index 00000000000..c1a98793d91 --- /dev/null +++ b/mysql-test/suite/innodb/t/undo_log.test @@ -0,0 +1,139 @@ +--source include/have_innodb.inc +CREATE TABLE test_tab ( +a_str_18 mediumtext, +b_str_3 varchar(32) DEFAULT NULL, +a_str_13 mediumtext, +b_str_5 varchar(40) DEFAULT NULL, +b_str_6 varchar(50) DEFAULT NULL, +b_str_7 char(32) DEFAULT NULL, +b_str_8 varchar(32) DEFAULT NULL, +b_str_9 varchar(255) DEFAULT NULL, +a_str_28 char(255) DEFAULT NULL, +a_str_27 varchar(255) DEFAULT NULL, +b_str_10 varchar(32) DEFAULT NULL, +a_str_26 varchar(255) DEFAULT NULL, +a_str_6 varchar(50) DEFAULT NULL, +b_str_11 varchar(32) DEFAULT NULL, +b_str_12 varchar(255) DEFAULT NULL, +b_str_13 char(32) DEFAULT NULL, +b_str_14 varchar(32) DEFAULT NULL, +b_str_15 char(32) DEFAULT NULL, +b_str_16 char(32) DEFAULT NULL, +b_str_17 varchar(32) DEFAULT NULL, +b_str_18 varchar(32) DEFAULT NULL, +a_str_25 varchar(40) DEFAULT NULL, +b_str_19 varchar(255) DEFAULT NULL, +a_str_23 varchar(40) DEFAULT NULL, +b_str_20 varchar(32) DEFAULT NULL, +a_str_21 varchar(255) DEFAULT NULL, +a_str_20 varchar(255) DEFAULT NULL, +a_str_39 varchar(255) DEFAULT NULL, +a_str_38 varchar(255) DEFAULT NULL, +a_str_37 varchar(255) DEFAULT NULL, +b_str_21 char(32) DEFAULT NULL, +b_str_23 varchar(80) DEFAULT NULL, +b_str_24 varchar(32) DEFAULT NULL, +b_str_25 varchar(32) DEFAULT NULL, +b_str_26 char(32) NOT NULL DEFAULT '', +b_str_27 varchar(255) DEFAULT NULL, +a_str_36 varchar(255) DEFAULT NULL, +a_str_33 varchar(100) DEFAULT NULL, +a_ref_10 char(32) DEFAULT NULL, +b_str_28 char(32) DEFAULT NULL, +b_str_29 char(32) DEFAULT NULL, +a_ref_6 char(32) DEFAULT NULL, +a_ref_12 varchar(32) DEFAULT NULL, +a_ref_11 varchar(32) DEFAULT NULL, +a_str_49 varchar(40) DEFAULT NULL, +b_str_30 varchar(32) DEFAULT NULL, +a_ref_3 varchar(32) DEFAULT NULL, +a_str_48 varchar(40) DEFAULT NULL, +a_ref_1 char(32) DEFAULT NULL, +b_str_31 varchar(32) DEFAULT NULL, +b_str_32 varchar(255) DEFAULT NULL, +b_str_33 char(32) DEFAULT NULL, +b_str_34 varchar(32) DEFAULT NULL, +a_str_47 varchar(40) DEFAULT NULL, +b_str_36 varchar(255) DEFAULT NULL, +a_str_46 varchar(40) DEFAULT NULL, +a_str_45 varchar(255) DEFAULT NULL, +b_str_38 varchar(32) DEFAULT NULL, +b_str_39 char(32) DEFAULT NULL, +b_str_40 varchar(32) DEFAULT NULL, +a_str_41 varchar(255) DEFAULT NULL, +b_str_41 varchar(32) DEFAULT NULL, +PRIMARY KEY (b_str_26), +UNIQUE KEY a_str_47 (a_str_47), +UNIQUE KEY a_str_49 (a_str_49), +UNIQUE KEY a_str_33 (a_str_33), +UNIQUE KEY a_str_46 (a_str_46), +UNIQUE KEY a_str_48 (a_str_48), +KEY b_str_18 (b_str_18), +KEY a_str_26 (a_str_26), +KEY b_str_27 (b_str_27,b_str_19), +KEY b_str_41 (b_str_41), +KEY b_str_15 (b_str_15), +KEY a_str_20 (a_str_20), +KEY b_str_17 (b_str_17), +KEY b_str_40 (b_str_40), +KEY b_str_24 (b_str_24), +KEY b_str_10 (b_str_10), +KEY b_str_16 (b_str_16), +KEY b_str_29 (b_str_29), +KEY a_str_41 (a_str_41), +KEY b_str_7 (b_str_7), +KEY a_str_45 (a_str_45), +KEY a_str_28 (a_str_28), +KEY a_str_37 (a_str_37), +KEY b_str_6 (b_str_6), +KEY a_ref_6 (a_ref_6), +KEY b_str_34 (b_str_34), +KEY b_str_38 (b_str_38), +KEY a_ref_10 (a_ref_10), +KEY b_str_21 (b_str_21), +KEY b_str_23 (b_str_23,b_str_19), +KEY b_str_33 (b_str_33), +KEY a_ref_12 (a_ref_12), +KEY a_str_18 (a_str_18(255)), +KEY a_str_39 (a_str_39), +KEY a_str_27 (a_str_27), +KEY a_str_25 (a_str_25), +KEY b_str_9 (b_str_9), +KEY a_str_23 (a_str_23), +KEY b_str_8 (b_str_8), +KEY a_str_21 (a_str_21), +KEY b_str_3 (b_str_3), +KEY b_str_30 (b_str_30), +KEY b_str_12 (b_str_12), +KEY b_str_25 (b_str_25), +KEY b_str_13 (b_str_13), +KEY a_str_38 (a_str_38), +KEY a_str_13 (a_str_13(255)), +KEY a_str_36 (a_str_36), +KEY b_str_28 (b_str_28), +KEY b_str_19 (b_str_19), +KEY b_str_11 (b_str_11), +KEY a_ref_1 (a_ref_1), +KEY b_str_20 (b_str_20), +KEY b_str_14 (b_str_14), +KEY a_ref_3 (a_ref_3), +KEY b_str_39 (b_str_39), +KEY b_str_32 (b_str_32), +KEY a_str_6 (a_str_6), +KEY b_str_5 (b_str_5), +KEY b_str_31 (b_str_31), +KEY a_ref_11 (a_ref_11) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT; + +BEGIN; +INSERT INTO test_tab (b_str_26, a_str_13, a_str_18) VALUES +('a', REPEAT('f',4031), REPEAT('g', 4031)); + +UPDATE test_tab SET a_str_13=REPEAT('h',4032), a_str_18=REPEAT('i',4032); +SELECT 'Reducing length to 4030'; +UPDATE test_tab SET a_str_13=REPEAT('j',4030), a_str_18=REPEAT('k',4030); +UPDATE test_tab SET a_str_13=REPEAT('l',4031), a_str_18=REPEAT('m',4031); +ROLLBACK; +SELECT COUNT(*) FROM test_tab; +CHECK TABLE test_tab; +DROP TABLE test_tab; diff --git a/mysql-test/suite/innodb_zip/r/innodb_prefix_index_liftedlimit.result b/mysql-test/suite/innodb_zip/r/innodb_prefix_index_liftedlimit.result index 746072781bd..6ac196770c4 100644 --- a/mysql-test/suite/innodb_zip/r/innodb_prefix_index_liftedlimit.result +++ b/mysql-test/suite/innodb_zip/r/innodb_prefix_index_liftedlimit.result @@ -584,12 +584,12 @@ REPEAT("a", 4000) , REPEAT("a", 255) CREATE INDEX prefix_idx3 ON worklog5743(col_3_text (3072)); CREATE INDEX prefix_idx4 ON worklog5743(col_4_blob (3072)); CREATE INDEX prefix_idx5 ON worklog5743(col_5_text (3072)); +BEGIN; UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000) WHERE col_1_varbinary = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000); -ERROR HY000: Undo log record is too big. SHOW WARNINGS; Level Code Message -Error 1713 Undo log record is too big. +ROLLBACK; DROP TABLE worklog5743; CREATE TABLE worklog5743 ( col_1_varbinary VARBINARY (4000) , col_2_varchar VARCHAR (4000) , @@ -627,13 +627,13 @@ REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000), REPEAT("a", 4000) , REPEAT("a", 255) ); ROLLBACK; +BEGIN; UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000) WHERE col_1_varbinary = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000); -ERROR HY000: Undo log record is too big. SHOW WARNINGS; Level Code Message -Error 1713 Undo log record is too big. +ROLLBACK; SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000); col_1_varbinary = REPEAT("c", 4000) diff --git a/mysql-test/suite/innodb_zip/t/innodb_prefix_index_liftedlimit.test b/mysql-test/suite/innodb_zip/t/innodb_prefix_index_liftedlimit.test index 77f55002da5..0c049b77630 100644 --- a/mysql-test/suite/innodb_zip/t/innodb_prefix_index_liftedlimit.test +++ b/mysql-test/suite/innodb_zip/t/innodb_prefix_index_liftedlimit.test @@ -534,10 +534,11 @@ REPEAT("a", 4000) , REPEAT("a", 255) CREATE INDEX prefix_idx3 ON worklog5743(col_3_text (3072)); CREATE INDEX prefix_idx4 ON worklog5743(col_4_blob (3072)); CREATE INDEX prefix_idx5 ON worklog5743(col_5_text (3072)); ---error ER_UNDO_RECORD_TOO_BIG +BEGIN; UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000) WHERE col_1_varbinary = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000); SHOW WARNINGS; +ROLLBACK; DROP TABLE worklog5743; #------------------------------------------------------------------------------ @@ -583,13 +584,12 @@ REPEAT("a", 4000) , REPEAT("o", 4000), REPEAT("a", 4000), REPEAT("a", 4000) , REPEAT("a", 255) ); ROLLBACK; -# Bug#12547647 - UPDATE LOGGING COULD EXCEED LOG PAGE SIZE -# Instead of this error, it would hang before this fix. ---error ER_UNDO_RECORD_TOO_BIG +BEGIN; UPDATE worklog5743 SET col_1_varbinary = REPEAT("c", 4000) WHERE col_1_varbinary = REPEAT("a", 4000) AND col_2_varchar = REPEAT("o", 4000); SHOW WARNINGS; +ROLLBACK; SELECT col_1_varbinary = REPEAT("c", 4000) FROM worklog5743 WHERE col_1_varbinary = REPEAT("c", 4000) AND col_2_varchar = REPEAT("o", 4000); INSERT INTO worklog5743 VALUES(REPEAT("a", 4000) , REPEAT("o", 4000), diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index f694cdd3d5e..8701fbcc0f5 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -772,7 +772,25 @@ trx_undo_page_report_modify( const dict_col_t* col = dict_table_get_nth_col(table, col_no); - if (col->ord_part) { + if (!col->ord_part) { + continue; + } + + if (update) { + for (i = 0; i < update->n_fields; i++) { + const dict_field_t* f + = dict_index_get_nth_field( + index, + upd_get_nth_field( + update, i) + ->field_no); + if (f->col == col) { + goto already_logged; + } + } + } + + if (TRUE) { ulint pos; /* Write field number to undo log */ @@ -822,6 +840,9 @@ trx_undo_page_report_modify( ptr += flen; } } + +already_logged: + continue; } mach_write_to_2(old_ptr, ptr - old_ptr); diff --git a/storage/xtradb/trx/trx0rec.cc b/storage/xtradb/trx/trx0rec.cc index 8c0904dd57b..3193dfd81b5 100644 --- a/storage/xtradb/trx/trx0rec.cc +++ b/storage/xtradb/trx/trx0rec.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 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 @@ -771,7 +772,25 @@ trx_undo_page_report_modify( const dict_col_t* col = dict_table_get_nth_col(table, col_no); - if (col->ord_part) { + if (!col->ord_part) { + continue; + } + + if (update) { + for (i = 0; i < update->n_fields; i++) { + const dict_field_t* f + = dict_index_get_nth_field( + index, + upd_get_nth_field( + update, i) + ->field_no); + if (f->col == col) { + goto already_logged; + } + } + } + + if (TRUE) { ulint pos; /* Write field number to undo log */ @@ -822,6 +841,9 @@ trx_undo_page_report_modify( ptr += flen; } } + +already_logged: + continue; } mach_write_to_2(old_ptr, ptr - old_ptr);