summaryrefslogtreecommitdiff
path: root/mysql-test
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-09-06 10:32:49 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-09-07 22:10:02 +0300
commitcf2a4426a2e864f35d002b1595fdffd4fe85ee4e (patch)
treed774d0a9657fae0496e039f446debb1acd8643d7 /mysql-test
parente67b1070bb0ca610c989af5d365bd342df511256 (diff)
downloadmariadb-git-cf2a4426a2e864f35d002b1595fdffd4fe85ee4e.tar.gz
MDEV-14717 RENAME TABLE in InnoDB is not crash-safe
This is a backport of commit 0bc36758ba08ddeea6f7896a0fb815a13a48895a and commit 9eb3fcc9fbccfb13ad26e5d9faa0f70b580f291e. InnoDB in MariaDB 10.2 appears to only write MLOG_FILE_RENAME2 redo log records during table-rebuilding ALGORITHM=INPLACE operations. We must write the records for any .ibd file renames, so that the operations are crash-safe. If InnoDB is killed during a RENAME TABLE operation, it can happen that the transaction for updating the data dictionary will be rolled back. But, nothing will roll back the renaming of the .ibd file (the MLOG_FILE_RENAME2 only guarantees roll-forward), or for that matter, the renaming of the dict_table_t::name in the dict_sys cache. We introduce the undo log record TRX_UNDO_RENAME_TABLE to fix this. fil_space_for_table_exists_in_mem(): Remove the parameters adjust_space, table_id and some code that was trying to work around these deficiencies. fil_name_write_rename(): Write a MLOG_FILE_RENAME2 record. dict_table_rename_in_cache(): Invoke fil_name_write_rename(). trx_undo_rec_copy(): Set the first 2 bytes to the length of the copied undo log record. trx_undo_page_report_rename(), trx_undo_report_rename(): Write a TRX_UNDO_RENAME_TABLE record with the old table name. row_rename_table_for_mysql(): Invoke trx_undo_report_rename() before modifying any data dictionary tables. row_undo_ins_parse_undo_rec(): Roll back TRX_UNDO_RENAME_TABLE by invoking dict_table_rename_in_cache(), which will take care of both renaming the table and the file. ha_innobase::truncate(): Remove a work-around.
Diffstat (limited to 'mysql-test')
-rw-r--r--mysql-test/suite/innodb/r/rename_table_debug.result12
-rw-r--r--mysql-test/suite/innodb/t/rename_table_debug.test19
2 files changed, 31 insertions, 0 deletions
diff --git a/mysql-test/suite/innodb/r/rename_table_debug.result b/mysql-test/suite/innodb/r/rename_table_debug.result
new file mode 100644
index 00000000000..912ed9de48b
--- /dev/null
+++ b/mysql-test/suite/innodb/r/rename_table_debug.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1 (a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(42);
+connect con1,localhost,root,,test;
+SET DEBUG_SYNC='before_rename_table_commit SIGNAL renamed WAIT_FOR ever';
+RENAME TABLE t1 TO t2;
+connection default;
+SET DEBUG_SYNC='now WAIT_FOR renamed';
+disconnect con1;
+SELECT * FROM t1;
+a
+42
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/rename_table_debug.test b/mysql-test/suite/innodb/t/rename_table_debug.test
new file mode 100644
index 00000000000..4620f7bef22
--- /dev/null
+++ b/mysql-test/suite/innodb/t/rename_table_debug.test
@@ -0,0 +1,19 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_debug_sync.inc
+--source include/not_embedded.inc
+
+CREATE TABLE t1 (a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(42);
+
+--connect (con1,localhost,root,,test)
+SET DEBUG_SYNC='before_rename_table_commit SIGNAL renamed WAIT_FOR ever';
+--send
+RENAME TABLE t1 TO t2;
+--connection default
+SET DEBUG_SYNC='now WAIT_FOR renamed';
+--let $shutdown_timeout=0
+--source include/restart_mysqld.inc
+--disconnect con1
+SELECT * FROM t1;
+DROP TABLE t1;