From 33f70c4d9c42b6e4da062312e1e4a4fb370313df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 12 Feb 2018 13:35:07 +0200 Subject: [PATCH 1/3] MDEV-13869 MariaDB slow start When code from MySQL 5.7.9 was merged to MariaDB 10.2.2 in commit 2e814d4702d71a04388386a9f591d14a35980bfe an assignment validate=true was inadvertently added to the function dict_check_sys_tables(). This causes InnoDB to open every single .ibd file on startup, even when no crash recovery was needed. Simply removing the assignment would make some tests fail. We do the best to retain almost the same level of inconsistency detection. In the test innodb.table_flags, access to one of the tables will not be blocked despite inconsistent flags. dict_check_sys_tables(): Remove the problematic assignment, and skip validation in normal startup. dict_load_table_one(): If the .ibd file cannot be opened, mark the table as corrupted and unreadable. fil_node_open_file(): Validate FSP_SPACE_FLAGS with the expected flags. If reading the tablespace fails, invalidate node->handle instead of letting it remain stale. This bug was caught by a fil_validate() assertion failure. fsp_flags_try_adjust(): If the tablespace file is invalid, do nothing. --- mysql-test/suite/innodb/r/table_flags.result | 13 ++++++++++--- mysql-test/suite/innodb/t/log_file_name.test | 1 + mysql-test/suite/innodb/t/table_flags.test | 5 +++-- storage/innobase/dict/dict0load.cc | 10 +++++++--- storage/innobase/fil/fil0fil.cc | 9 +++++++-- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/innodb/r/table_flags.result b/mysql-test/suite/innodb/r/table_flags.result index 435fe8fc45e..3684242f765 100644 --- a/mysql-test/suite/innodb/r/table_flags.result +++ b/mysql-test/suite/innodb/r/table_flags.result @@ -116,14 +116,21 @@ SHOW CREATE TABLE tr; ERROR 42S02: Table 'test.tr' doesn't exist in engine SHOW CREATE TABLE tc; ERROR 42S02: Table 'test.tc' doesn't exist in engine +SELECT * FROM tc; +ERROR 42S02: Table 'test.tc' doesn't exist in engine SHOW CREATE TABLE td; -ERROR 42S02: Table 'test.td' doesn't exist in engine +Table Create Table +td CREATE TABLE `td` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC +SELECT * FROM td; +a SHOW CREATE TABLE tz; ERROR 42S02: Table 'test.tz' doesn't exist in engine SHOW CREATE TABLE tp; ERROR 42S02: Table 'test.tp' doesn't exist in engine -FOUND 6 /InnoDB: Table `test`.`t[czp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err -FOUND 2 /InnoDB: Refusing to load '\..test.td\.ibd' \(id=3, flags=0x1?[2ae]1\); dictionary contains id=3, flags=0x10[01][2ae]1\b/ in mysqld.1.err +FOUND 7 /InnoDB: Table `test`.`t[czp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649/ in mysqld.1.err FOUND 2 /InnoDB: Table `test`\.`tr` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b/ in mysqld.1.err Restoring SYS_TABLES clustered index root page (8) SHOW CREATE TABLE tr; diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index 2ee8c49aa7c..87c1681d443 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -163,6 +163,7 @@ call mtr.add_suppression("InnoDB: Cannot rename.*because the target file exists" call mtr.add_suppression("InnoDB: Log scan aborted at LSN"); # The following are for the --innodb-force-recovery=1 with broken u* tables: call mtr.add_suppression("InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd"); +call mtr.add_suppression("InnoDB: The size of the file .*u1\\.ibd is only 16384 bytes, should be at least 65536"); call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified"); call mtr.add_suppression("InnoDB: .*you must create directories"); call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: '.*u[1-5]\.ibd'"); diff --git a/mysql-test/suite/innodb/t/table_flags.test b/mysql-test/suite/innodb/t/table_flags.test index b8ccc4ce4b6..02d5a744e2c 100644 --- a/mysql-test/suite/innodb/t/table_flags.test +++ b/mysql-test/suite/innodb/t/table_flags.test @@ -14,6 +14,7 @@ call mtr.add_suppression("InnoDB: Ignoring tablespace for `test`.`td` because it call mtr.add_suppression("InnoDB: Operating system error number .* in a file operation"); call mtr.add_suppression("InnoDB: The error means the system cannot find the path specified"); call mtr.add_suppression("InnoDB: If you are installing InnoDB, remember that you must create directories yourself"); +call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of tablespace"); FLUSH TABLES; --enable_query_log @@ -133,7 +134,9 @@ SHOW CREATE TABLE tr; --error ER_NO_SUCH_TABLE_IN_ENGINE SHOW CREATE TABLE tc; --error ER_NO_SUCH_TABLE_IN_ENGINE +SELECT * FROM tc; SHOW CREATE TABLE td; +SELECT * FROM td; --error ER_NO_SUCH_TABLE_IN_ENGINE SHOW CREATE TABLE tz; --error ER_NO_SUCH_TABLE_IN_ENGINE @@ -144,8 +147,6 @@ SHOW CREATE TABLE tp; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; --let SEARCH_PATTERN= InnoDB: Table `test`.`t[czp]` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=(129|289|3873|1232[13]) SYS_TABLES\.N_COLS=2147483649 --source include/search_pattern_in_file.inc ---let SEARCH_PATTERN= InnoDB: Refusing to load '\..test.td\.ibd' \(id=3, flags=0x1?[2ae]1\); dictionary contains id=3, flags=0x10[01][2ae]1\b ---source include/search_pattern_in_file.inc --let SEARCH_PATTERN= InnoDB: Table `test`\.`tr` in InnoDB data dictionary contains invalid flags\. SYS_TABLES\.TYPE=65 SYS_TABLES\.MIX_LEN=4294967295\b --source include/search_pattern_in_file.inc diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 15e14b9d9f7..3606b902510 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2017, MariaDB Corporation. +Copyright (c) 2016, 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 @@ -1471,8 +1471,6 @@ dict_check_sys_tables( char* filepath = dict_get_first_path(space_id); /* Check that the .ibd file exists. */ - validate = true; /* Encryption */ - dberr_t err = fil_ibd_open( validate, !srv_read_only_mode && srv_log_file_size != 0, @@ -3078,6 +3076,12 @@ err_exit: } else { dict_mem_table_fill_foreign_vcol_set(table); table->fk_max_recusive_level = 0; + + if (table->space + && !fil_space_get_size(table->space)) { + table->corrupted = true; + table->file_unreadable = true; + } } } else { dict_index_t* index; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 0598b687d91..f3bb127020a 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -624,6 +624,7 @@ retry: << " is only " << size_bytes << " bytes, should be at least " << min_size; os_file_close(node->handle); + node->handle = OS_FILE_CLOSED; return(false); } @@ -661,10 +662,12 @@ retry: ut_free(buf2); os_file_close(node->handle); + node->handle = OS_FILE_CLOSED; if (!fsp_flags_is_valid(flags, space->id)) { ulint cflags = fsp_flags_convert_from_101(flags); - if (cflags == ULINT_UNDEFINED) { + if (cflags == ULINT_UNDEFINED + || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) { ib::error() << "Expected tablespace flags " << ib::hex(space->flags) @@ -4626,7 +4629,9 @@ fsp_flags_try_adjust(ulint space_id, ulint flags) { ut_ad(!srv_read_only_mode); ut_ad(fsp_flags_is_valid(flags, space_id)); - + if (!fil_space_get_size(space_id)) { + return; + } mtr_t mtr; mtr.start(); if (buf_block_t* b = buf_page_get( From 00f0c039d2f4213ccf0a0202349ecb162a799989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 12 Feb 2018 16:40:05 +0200 Subject: [PATCH 2/3] MDEV-15270 Mariabackup should not try to use doublewrite buffer When Mariabackup gets a bad read of the first page of the system tablespace file, it would inappropriately try to apply the doublewrite buffer and write changes back to the data file (to the source file)! This is very wrong and must be prevented. The correct action would be to retry reading the system tablespace as well as any other files whose first page was read incorrectly. Fixing this was not attempted. xb_load_tablespaces(): Shorten a bogus message to be more relevant. The message can be displayed by --backup or --prepare. xtrabackup_backup_func(), os_file_write_func(): Add a missing space to a message. Datafile::restore_from_doublewrite(): Do not even attempt the operation in Mariabackup. recv_init_crash_recovery_spaces(): Do not attempt to restore the doublewrite buffer in Mariabackup (--prepare or --export), because all pages should have been copied correctly in --backup already, and because --backup should ignore the doublewrite buffer. SysTablespace::read_lsn_and_check_flags(): Do not attempt to initialize the doublewrite buffer in Mariabackup. innodb_make_page_dirty(): Correct the bounds check. Datafile::read_first_page(): Correct the name of the parameter. --- extra/mariabackup/xtrabackup.cc | 16 ++-------------- mysql-test/suite/mariabackup/huge_lsn.test | 1 - storage/innobase/fsp/fsp0file.cc | 6 +++++- storage/innobase/fsp/fsp0sysspace.cc | 5 +++-- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/fsp0file.h | 3 ++- storage/innobase/log/log0recv.cc | 4 +++- storage/innobase/os/os0file.cc | 4 ++-- 8 files changed, 18 insertions(+), 23 deletions(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 2d2734e0f30..7ac168b1778 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -2908,19 +2908,7 @@ xb_load_tablespaces() &flush_lsn); if (err != DB_SUCCESS) { - msg("mariabackup: Could not open or create data files.\n" - "mariabackup: If you tried to add new data files, and it " - "failed here,\n" - "mariabackup: you should now edit innodb_data_file_path in " - "my.cnf back\n" - "mariabackup: to what it was, and remove the new ibdata " - "files InnoDB created\n" - "mariabackup: in this failed attempt. InnoDB only wrote " - "those files full of\n" - "mariabackup: zeros, but did not yet use them in any way. " - "But be careful: do not\n" - "mariabackup: remove old data files which contain your " - "precious data!\n"); + msg("mariabackup: Could not open data files.\n"); return(err); } @@ -3859,7 +3847,7 @@ reread_log_header: err = xb_load_tablespaces(); if (err != DB_SUCCESS) { msg("mariabackup: error: xb_load_tablespaces() failed with" - "error code %u\n", err); + " error code %u\n", err); goto fail; } diff --git a/mysql-test/suite/mariabackup/huge_lsn.test b/mysql-test/suite/mariabackup/huge_lsn.test index 417d40c8e7a..9e72f0ad8d0 100644 --- a/mysql-test/suite/mariabackup/huge_lsn.test +++ b/mysql-test/suite/mariabackup/huge_lsn.test @@ -28,7 +28,6 @@ EOF --remove_files_wildcard $MYSQLD_DATADIR ib_logfile* --source include/start_mysqld.inc -let SEARCH_RANGE= -50000; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; --let SEARCH_PATTERN= InnoDB: New log files created, LSN=175964\d{8} --source include/search_pattern_in_file.inc diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index c21c9497735..eaadaad851d 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, 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 @@ -770,6 +770,10 @@ the double write buffer. bool Datafile::restore_from_doublewrite() { + if (srv_operation != SRV_OPERATION_NORMAL) { + return true; + } + /* Find if double write buffer contains page_no of given space id. */ const byte* page = recv_sys->dblwr.find_page(m_space_id, 0); const page_id_t page_id(m_space_id, 0); diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc index c459c8296e0..e9f04cbd6c5 100644 --- a/storage/innobase/fsp/fsp0sysspace.cc +++ b/storage/innobase/fsp/fsp0sysspace.cc @@ -567,8 +567,9 @@ SysTablespace::read_lsn_and_check_flags(lsn_t* flushed_lsn) ut_a(it->order() == 0); - - buf_dblwr_init_or_load_pages(it->handle(), it->filepath()); + if (srv_operation == SRV_OPERATION_NORMAL) { + buf_dblwr_init_or_load_pages(it->handle(), it->filepath()); + } /* Check the contents of the first page of the first datafile. */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index fae784ff12c..d256f42f2f6 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18571,7 +18571,7 @@ innodb_make_page_dirty( return; } - if (srv_saved_page_number_debug > space->size) { + if (srv_saved_page_number_debug >= space->size) { fil_space_release(space); return; } diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h index 1f057be0877..68e9f687fcd 100644 --- a/storage/innobase/include/fsp0file.h +++ b/storage/innobase/include/fsp0file.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -363,7 +364,7 @@ private: @param[in] read_only_mode if true, then readonly mode checks are enforced. @return DB_SUCCESS or DB_IO_ERROR if page cannot be read */ - dberr_t read_first_page(bool read_first_page) + dberr_t read_first_page(bool read_only_mode) MY_ATTRIBUTE((warn_unused_result)); /** Free the first page from memory when it is no longer needed. */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 818a0f0422e..e55c01aca3a 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -3147,7 +3147,9 @@ recv_init_crash_recovery_spaces() << "', but there were no modifications either."; } - buf_dblwr_process(); + if (srv_operation == SRV_OPERATION_NORMAL) { + buf_dblwr_process(); + } if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { /* Spawn the background thread to flush dirty pages diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 51227696c1c..a824afc6e0e 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Percona Inc.. Those modifications are @@ -4994,7 +4994,7 @@ os_file_write_func( if ((ulint) n_bytes != n && !os_has_said_disk_full) { ib::error() - << "Write to file " << name << "failed at offset " + << "Write to file " << name << " failed at offset " << offset << ", " << n << " bytes should have been written," " only " << n_bytes << " were written." From c051eaba46f2a9570bba3f3a64708502ff0aa03c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 13 Feb 2018 13:01:14 +0200 Subject: [PATCH 3/3] MDEV-14988 innodb_read_only tries to modify files if transactions were recovered in COMMITTED state lock_trx_release_locks(): Relax a debug assertion to allow recovered TRX_STATE_COMMITTED_IN_MEMORY transactions. trx_commit_in_memory(): Add DEBUG_SYNC instrumentation. trx_undo_insert_cleanup(): Skip persistent changes if innodb_read_only is set. This should only happen when a recovered committed transaction would be cleaned up at shutdown. --- .../r/read_only_recover_committed.result | 43 ++++++++++++ .../innodb/t/read_only_recover_committed.test | 68 +++++++++++++++++++ storage/innobase/lock/lock0lock.cc | 5 +- storage/innobase/trx/trx0trx.cc | 4 +- storage/innobase/trx/trx0undo.cc | 6 +- storage/xtradb/lock/lock0lock.cc | 5 +- storage/xtradb/trx/trx0trx.cc | 4 +- storage/xtradb/trx/trx0undo.cc | 6 +- 8 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/innodb/r/read_only_recover_committed.result create mode 100644 mysql-test/suite/innodb/t/read_only_recover_committed.test diff --git a/mysql-test/suite/innodb/r/read_only_recover_committed.result b/mysql-test/suite/innodb/r/read_only_recover_committed.result new file mode 100644 index 00000000000..593bcae40ee --- /dev/null +++ b/mysql-test/suite/innodb/r/read_only_recover_committed.result @@ -0,0 +1,43 @@ +CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t VALUES(1); +BEGIN; +INSERT INTO t VALUES(2); +DELETE FROM t WHERE a=2; +# Normal MariaDB shutdown would roll back the above transaction. +# We want the transaction to remain open, so we will kill the server +# after ensuring that any non-transactional files are clean. +FLUSH TABLES; +# Create another transaction that will be recovered as COMMITTED. +BEGIN; +SET DEBUG_SYNC='after_trx_committed_in_memory SIGNAL committed WAIT_FOR ever'; +COMMIT; +SET DEBUG_SYNC='now WAIT_FOR committed'; +# Ensure that the above incomplete transactions become durable. +SET GLOBAL innodb_flush_log_at_trx_commit=1; +BEGIN; +INSERT INTO t VALUES(-10000); +ROLLBACK; +SELECT * FROM t; +a +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT * FROM t; +a +1 +UPDATE t SET a=3 WHERE a=1; +ERROR HY000: Table 't' is read only +# Starting with MariaDB 10.2, innodb_read_only implies READ UNCOMMITTED. +# In earlier versions, this would return the last committed version +# (empty table)! +SELECT * FROM t; +a +1 +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT * FROM t; +a +1 +SELECT * FROM t; +a +1 +DROP TABLE t; +NOT FOUND /Rolled back recovered transaction [^0]/ in mysqld.1.err diff --git a/mysql-test/suite/innodb/t/read_only_recover_committed.test b/mysql-test/suite/innodb/t/read_only_recover_committed.test new file mode 100644 index 00000000000..402cbeba1b9 --- /dev/null +++ b/mysql-test/suite/innodb/t/read_only_recover_committed.test @@ -0,0 +1,68 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc +# need to restart server +--source include/not_embedded.inc + +--connect(con1, localhost, root) +CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t VALUES(1); +BEGIN; +# Generate insert_undo log. +INSERT INTO t VALUES(2); +# Generate update_undo log. +DELETE FROM t WHERE a=2; +--connect(con2, localhost, root) +--echo # Normal MariaDB shutdown would roll back the above transaction. +--echo # We want the transaction to remain open, so we will kill the server +--echo # after ensuring that any non-transactional files are clean. +FLUSH TABLES; +--echo # Create another transaction that will be recovered as COMMITTED. +BEGIN; +# Generate multiple pages of both insert_undo and update_undo, so that +# the state TRX_UNDO_CACHE will not be chosen. +--disable_query_log +let $n= 10000; +while ($n) { +dec $n; +eval INSERT INTO t VALUES(-$n); +eval DELETE FROM t WHERE a=-$n; +} +--enable_query_log +SET DEBUG_SYNC='after_trx_committed_in_memory SIGNAL committed WAIT_FOR ever'; +send COMMIT; + +connection default; +SET DEBUG_SYNC='now WAIT_FOR committed'; +--echo # Ensure that the above incomplete transactions become durable. +SET GLOBAL innodb_flush_log_at_trx_commit=1; +BEGIN; +INSERT INTO t VALUES(-10000); +ROLLBACK; +--let $restart_parameters= --innodb-force-recovery=3 +--let $shutdown_timeout= 0 +--source include/restart_mysqld.inc +--let $shutdown_timeout= 30 +--disconnect con1 +--disconnect con2 +SELECT * FROM t; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT * FROM t; +# refused on MySQL 5.6, MariaDB 10.0, 10.1, but not MariaDB 10.2+ +--error ER_OPEN_AS_READONLY +UPDATE t SET a=3 WHERE a=1; +--let $restart_parameters= --innodb-read-only +--source include/restart_mysqld.inc +--echo # Starting with MariaDB 10.2, innodb_read_only implies READ UNCOMMITTED. +--echo # In earlier versions, this would return the last committed version +--echo # (empty table)! +SELECT * FROM t; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +SELECT * FROM t; +--let $restart_parameters= +--source include/restart_mysqld.inc +SELECT * FROM t; +DROP TABLE t; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +--let SEARCH_PATTERN= Rolled back recovered transaction [^0] +--source include/search_pattern_in_file.inc diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index aa232f89b60..1e91ce45633 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -7000,7 +7000,10 @@ lock_trx_release_locks( } mutex_exit(&trx_sys->mutex); } else { - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); + ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) + || (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY) + && trx->is_recovered + && !UT_LIST_GET_LEN(trx->lock.trx_locks))); } /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 8974bfc2904..4a332d22cbc 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, 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 @@ -1227,6 +1227,8 @@ trx_commit_in_memory( trx->read_view = NULL; if (lsn) { + DEBUG_SYNC_C("after_trx_committed_in_memory"); + if (trx->insert_undo != NULL) { trx_undo_insert_cleanup(trx); diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index d6bcd131a4f..370b3f181a1 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup( mutex_exit(&(rseg->mutex)); - trx_undo_seg_free(undo); + if (!srv_read_only_mode) { + trx_undo_seg_free(undo); + } mutex_enter(&(rseg->mutex)); diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index 2a918158612..9dc82daecf8 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -7099,7 +7099,10 @@ lock_trx_release_locks( } mutex_exit(&trx_sys->mutex); } else { - ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE)); + ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) + || (trx_state_eq(trx, TRX_STATE_COMMITTED_IN_MEMORY) + && trx->is_recovered + && !UT_LIST_GET_LEN(trx->lock.trx_locks))); } /* The transition of trx->state to TRX_STATE_COMMITTED_IN_MEMORY diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc index 45578283235..701ac3ed72d 100644 --- a/storage/xtradb/trx/trx0trx.cc +++ b/storage/xtradb/trx/trx0trx.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, 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 @@ -1442,6 +1442,8 @@ trx_commit_in_memory( if (lsn) { ulint flush_log_at_trx_commit; + DEBUG_SYNC_C("after_trx_committed_in_memory"); + if (trx->insert_undo != NULL) { trx_undo_insert_cleanup(trx); diff --git a/storage/xtradb/trx/trx0undo.cc b/storage/xtradb/trx/trx0undo.cc index d6bcd131a4f..370b3f181a1 100644 --- a/storage/xtradb/trx/trx0undo.cc +++ b/storage/xtradb/trx/trx0undo.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. +Copyright (c) 2014, 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 @@ -1989,7 +1989,9 @@ trx_undo_insert_cleanup( mutex_exit(&(rseg->mutex)); - trx_undo_seg_free(undo); + if (!srv_read_only_mode) { + trx_undo_seg_free(undo); + } mutex_enter(&(rseg->mutex));