summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0mysql.cc
Commit message (Collapse)AuthorAgeFilesLines
* Merge 10.3 into 10.4Marko Mäkelä2019-01-181-2/+5
|\
| * Merge 10.2 into 10.3Marko Mäkelä2019-01-181-2/+5
| |\
| | * Merge 10.1 into 10.2Marko Mäkelä2019-01-181-2/+5
| | |\
| | | * MDEV-18237 InnoDB: Unable to drop FTS index aux table and further errors ↵Marko Mäkelä2019-01-181-2/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | (possibly bogus) row_drop_table_for_mysql(): Fix a regression introduced in MDEV-16515. Similar to the follow-up fixes MDEV-16647 and MDEV-17470, we must make the internal tables of FULLTEXT INDEX immune to kills, to avoid noise and resource leakage on DROP TABLE or ALTER TABLE. (Orphan internal tables would be dropped at the next InnoDB startup only.)
| | | * Merge branch '10.0' into 10.1Sergei Golubchik2018-12-291-1/+2
| | | |\
| | | | * row_drop_table_for_mysql(): Correct a parameter to innobase_format_name()Marko Mäkelä2018-12-281-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This fixes a regression that was introduced in MySQL 5.6.6 in an error handling code path, in the following change: commit 024f363d6b5f09b20d1bba411af55be95c7398d3 Author: kevin.lewis@oracle.com <> Date: Fri Jun 15 09:01:42 2012 -0500 Bug #14169459 INNODB; DROP TABLE DOES NOT DELETE THE IBD FILE FOR A TEMPORARY TABLE.
* | | | | Merge 10.3 into 10.4Marko Mäkelä2019-01-061-6/+11
|\ \ \ \ \ | |/ / / /
| * | | | Merge branch '10.2' into 10.3Sergei Golubchik2019-01-031-6/+11
| |\ \ \ \ | | |/ / /
| | * | | Merge 10.1 into 10.2Marko Mäkelä2018-12-281-6/+10
| | |\ \ \ | | | |/ /
| | | * | MDEV-17470 Orphan temporary files after interrupted ALTER cause InnoDB: ↵Eugene Kosov2018-12-281-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Operating system error number 17 and eventual fatal error 71 Orphan #sql* tables may remain after ALTER TABLE was interrupted by timeout or KILL or client disconnect. This is a regression caused by MDEV-16515. Similar to temporary tables (MDEV-16647), we had better ignore the KILL when dropping the original table in the final part of ALTER TABLE. Closes #1020
* | | | | MDEV-17899: Fix a regression from MDEV-17793Marko Mäkelä2018-12-111-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The fix of MDEV-17793 was updating SYS_INDEXES.TABLE_ID in order to make the table invisible to purge (lazily delete old undo log records). By design of InnoDB, an update of TABLE_ID cannot be rolled back, because the rollback would effectively drop all indexes of the table due to the internal 'trigger' on SYS_INDEXES modifications. So, we revert the code change of MDEV-17793 and instead fix MDEV-17793 in a different way: by tweaking the undo log parsing during purge. The MDEV-17793 bug scenario is that a table becomes empty and a third instant ALTER TABLE is executed before purge processes the undo log record for the second instant ALTER TABLE. After this point, when purge sees the record, the table could have a mismatching number of rows. The test case works with this alternative fix. But what about a scenario where a fourth instant ALTER TABLE arrives before purge processes the second one? Could anything bad happen? Purge is only doing two things: First, free any BLOBs that were affected by the update record, and then, reset the DB_TRX_ID,DB_ROLL_PTR if a matching record is found. For the hidden metadata record, the only BLOB that we update is the hidden metadata BLOB that was introduced by MDEV-15562. Any other BLOBs (for the initial default values of instantly added columns) are never updated. So, in our scenario, the metadata BLOB that was created by the first instant ALTER TABLE (if it involved dropping or permuting columns) would be freed by purge when it is processing the undo record of the second ALTER TABLE. The BLOB value that was written by the second ALTER TABLE should be freed when the table is emptied. This is currently not done: MDEV-17383 should fix that. There is no possibility of double-free, because purge would only free old values of BLOBs. What about MVCC and other callers of trx_undo_update_rec_get_update()? The answer is simple: they should never be accessing the hidden metadata record in the first place. dict_table_t::reassign_id(): Remove. btr_cur_pessimistic_delete(): Clarify a comment. row_mysql_table_id_reassign(), row_discard_tablespace_for_mysql(): Add comments explaining that the operation cannot be rolled back. trx_undo_update_rec_get_update(): Avoid out-of-bounds access when parsing a metadata record. Avoid unnecessary memory allocation when filtering out fields from the update vector.
* | | | | Merge 10.3 into 10.4Marko Mäkelä2018-12-101-3/+6
|\ \ \ \ \ | |/ / / /
| * | | | Merge 10.2 into 10.3Marko Mäkelä2018-12-101-3/+6
| |\ \ \ \ | | |/ / /
| | * | | MDEV-17938 ALTER TABLE reports ER_TABLESPACE_EXISTS after failed ALTER TABLEMarko Mäkelä2018-12-101-3/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There was a race condition in the error handling of ALTER TABLE when the table contains FULLTEXT INDEX. During the error handling of an erroneous ALTER TABLE statement, when InnoDB would drop the internally created tables for FULLTEXT INDEX, it could happen that one of the hidden tables was being concurrently accessed by a background thread. Because of this, InnoDB would defer the drop operation to the background. However, related to MDEV-13564 backup-safe TRUNCATE TABLE and its prerequisite MDEV-14585, we had to make the background drop table queue crash-safe by renaming the table to a temporary name before enqueueing it. This renaming was introduced in a follow-up of the MDEV-13407 fix. As part of this rename operation, we were unnecessarily parsing the current SQL statement, because the same rename operation could also be executed as part of ALTER TABLE via ha_innobase::rename_table(). If an ALTER TABLE statement was being refused due to incorrectly formed FOREIGN KEY constraint, then it could happen that the renaming of the hidden internal tables for FULLTEXT INDEX could also fail, triggering a host of error log messages, and causing a subsequent table-rebuilding ALTER TABLE operation to fail due to the tablespace already existing. innobase_rename_table(), row_rename_table_for_mysql(): Add the parameter use_fk for suppressing the parsing of FOREIGN KEY constraints. It will only be passed as use_fk=true by ha_innobase::rename_table(), which can be invoked as part of ALTER TABLE...ALGORITHM=COPY.
* | | | | Merge 10.3 into 10.4Marko Mäkelä2018-11-301-82/+0
|\ \ \ \ \ | |/ / / /
| * | | | Merge 10.2 into 10.3Marko Mäkelä2018-11-301-84/+0
| |\ \ \ \ | | |/ / / | | | | | | | | | | | | | | | | | | | | Also, related to MDEV-15522, MDEV-17304, MDEV-17835, remove the Galera xtrabackup tests, because xtrabackup never worked with MariaDB Server 10.3 due to InnoDB redo log format changes.
| | * | | MDEV-17859: Clean up the FOREIGN KEY handlingMarko Mäkelä2018-11-291-90/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dict_create_add_foreigns_to_dictionary(): Do not commit the transaction. The operation can still fail in dict_load_foreigns(), and we want to be able to roll back the transaction. create_table_info_t::create_table(): Never reset m_drop_before_rollback, and never commit the transaction. We use a single point of rollback in ha_innobase::create(). Merge the logic from row_table_add_foreign_constraints().
* | | | | Merge 10.3 into 10.4Marko Mäkelä2018-11-261-32/+8
|\ \ \ \ \ | |/ / / /
| * | | | Merge 10.2 into 10.3Marko Mäkelä2018-11-261-36/+6
| |\ \ \ \ | | |/ / / | | | | | | | | | | | | | | | The test galera_sst_mariabackup_table_options was disabled, because the server refuses to start up due to wrong parameters.
| | * | | MDEV-17816 Crash in TRUNCATE TABLE when table creation failsMarko Mäkelä2018-11-261-24/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The error handling in the MDEV-13564 TRUNCATE TABLE was broken when an error occurred during table creation. row_create_index_for_mysql(): Do not drop the table on error. fts_create_one_common_table(), fts_create_one_index_table(): Do drop the table on error. create_index(), create_table_info_t::create_table(): Let the caller handle the index creation errors. ha_innobase::create(): If create_table_info_t::create_table() fails, drop the incomplete table, roll back the transaction, and finally return an error to the caller.
| * | | | MDEV-12266: Remove a level of pointer indirectionMarko Mäkelä2018-11-221-2/+2
| | | | | | | | | | | | | | | | | | | | Replace table->space->id with table->space_id.
* | | | | MDEV-17794 Do not assign persistent ID for temporary tablesMarko Mäkelä2018-11-221-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | InnoDB in MySQL 5.7 introduced two new parameters to the function dict_hdr_get_new_id(), to allow redo logging to be disabled when assigning identifiers to temporary tables or during the backup-unfriendly TRUNCATE TABLE that was replaced in MariaDB by MDEV-13564. Now that MariaDB 10.4.0 removed the crash recovery code for the backup-unfriendly TRUNCATE, we can revert dict_hdr_get_new_id() to be used only for persistent data structures. dict_table_assign_new_id(): Remove. This was a simple 2-line function that was called from few places. dict_table_open_on_id_low(): Declare in the only file where it is called. dict_sys_t::temp_id_hash: A separate lookup table for temporary tables. Table names will be in the common dict_sys_t::table_hash. dict_sys_t::get_temporary_table_id(): Assign a temporary table ID. dict_sys_t::get_table(): Look up a persistent table. dict_sys_t::get_temporary_table(): Look up a temporary table. dict_sys_t::temp_table_id: The sequence of temporary table identifiers. Starts from DICT_HDR_FIRST_ID, so that we can continue to simply compare dict_table_t::id to a few constants for the persistent hard-coded data dictionary tables. undo_node_t::state: Distinguish temporary and persistent tables. lock_check_dict_lock(), lock_get_table_id(): Assert that there cannot be locks on temporary tables. row_rec_to_index_entry_impl(): Assert that there cannot be metadata records on temporary tables. row_undo_ins_parse_undo_rec(): Distinguish temporary and persistent tables. Move some assertions from the only caller. Return whether the table was found. row_undo_ins(): Add some assertions. row_undo_mod_clust(), row_undo_mod(): Do not assign node->state. Let row_undo() do that. row_undo_mod_parse_undo_rec(): Distinguish temporary and persistent tables. Move some assertions from the only caller. Return whether the table was found. row_undo_try_truncate(): Renamed and simplified from trx_roll_try_truncate(). row_undo_rec_get(): Replaces trx_roll_pop_top_rec_of_trx() and trx_roll_pop_top_rec(). Fetch an undo log record, and assign undo->state accordingly. trx_undo_truncate_end(): Acquire the rseg->mutex only for the minimum required duration, and release it between mini-transactions.
* | | | | Merge 10.3 into 10.4Marko Mäkelä2018-11-191-3/+1
|\ \ \ \ \ | |/ / / /
| * | | | Merge 10.2 into 10.3Marko Mäkelä2018-11-191-3/+1
| |\ \ \ \ | | |/ / /
| | * | | Remove many redundant #include from InnoDBMarko Mäkelä2018-11-191-3/+1
| | | | |
* | | | | MDEV-17750: Remove dict_index_get_sys_col_pos()Marko Mäkelä2018-11-161-1/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dict_index_t::db_trx_id(): Return the position of DB_TRX_ID. Only valid for the clustered index. dict_index_t::db_roll_ptr(): Return the position of DB_ROLL_PTR. Only valid for the clustered index. dict_index_get_sys_col_pos(): Remove. This was performing unnecessarily complex computations, which only made sense for DB_ROW_ID, which would exist either as the first field in the clustered index or as the last field in a secondary index (only when a DB_ROW_ID column is materialised). row_sel_store_row_id_to_prebuilt(): Remove, and replace with simpler code. row_upd_index_entry_sys_field(): Remove. btr_cur_log_sys(): Replaces row_upd_write_sys_vals_to_log(). btr_cur_write_sys(): Write DB_TRX_ID,DB_ROLL_PTR to a data tuple.
* | | | | Merge 10.3 into 10.4Marko Mäkelä2018-11-061-105/+91
|\ \ \ \ \ | |/ / / /
| * | | | Merge 10.2 into 10.3Marko Mäkelä2018-11-061-105/+91
| |\ \ \ \ | | |/ / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | main.derived_cond_pushdown: Move all 10.3 tests to the end, trim trailing white space, and add an "End of 10.3 tests" marker. Add --sorted_result to tests where the ordering is not deterministic. main.win_percentile: Add --sorted_result to tests where the ordering is no longer deterministic.
| | * | | Merge 10.1 into 10.2Marko Mäkelä2018-11-061-3/+4
| | |\ \ \ | | | |/ /
| | | * | Fix innodb.table_flags,debugMarko Mäkelä2018-10-311-1/+3
| | | | |
| | | * | Merge branch '10.0' into 10.1Sergei Golubchik2018-10-311-85/+78
| | | |\ \ | | | | |/
| | | | * MDEV-12023 Assertion failure sym_node->table != NULL on startupMarko Mäkelä2018-10-301-85/+78
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | row_drop_table_for_mysql(): Avoid accessing non-existing dictionary tables. dict_create_or_check_foreign_constraint_tables(): Add debug instrumentation for creating and dropping a table before the creation of any non-core dictionary tables. trx_purge_add_update_undo_to_history(): Adjust a debug assertion, so that it will not fail due to the test instrumentation.
| | | * | Merge branch '10.0' into 10.1Sergei Golubchik2018-10-301-2/+6
| | | |\ \ | | | | |/
| | | | * Merge branch 'merge/merge-innodb-5.6' into 10.0Sergei Golubchik2018-10-281-0/+3
| | | | |\
| | | | | * 5.6.42Sergei Golubchik2018-10-271-0/+3
| | | | | |
| | | | * | MDEV-17531 Crash in RENAME TABLE with FOREIGN KEY and FULLTEXT INDEXMarko Mäkelä2018-10-251-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In RENAME TABLE, when an error occurs while renaming FOREIGN KEY constraint, that error would be overwritten when renaming the InnoDB internal tables related to FULLTEXT INDEX. row_rename_table_for_mysql(): Do not attempt to rename the internal tables if an error already occurred. This problem was originally reported as Oracle Bug#27545888.
| | | * | | compiler warnings (clang 4.0.1 on i386)Sergei Golubchik2018-09-041-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | extra/mariabackup/fil_cur.cc:361:42: warning: format specifies type 'unsigned long' but the argument has type 'ib_int64_t' (aka 'long long') [-Wformat] extra/mariabackup/fil_cur.cc:376:9: warning: format specifies type 'unsigned long' but the argument has type 'ib_int64_t' (aka 'long long') [-Wformat] sql/handler.cc:6196:45: warning: format specifies type 'unsigned long' but the argument has type 'wsrep_trx_id_t' (aka 'unsigned long long') [-Wformat] sql/log.cc:1681:16: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat] sql/log.cc:1687:16: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat] sql/wsrep_sst.cc:1388:86: warning: format specifies type 'long' but the argument has type 'wsrep_seqno_t' (aka 'long long') [-Wformat] sql/wsrep_sst.cc:232:86: warning: format specifies type 'long' but the argument has type 'wsrep_seqno_t' (aka 'long long') [-Wformat] storage/connect/filamdbf.cpp:450:47: warning: format specifies type 'short' but the argument has type 'int' [-Wformat] storage/connect/filamdbf.cpp:970:47: warning: format specifies type 'short' but the argument has type 'int' [-Wformat] storage/connect/inihandl.cpp:197:16: warning: address of array 'key->name' will always evaluate to 'true' [-Wpointer-bool-conversion] storage/innobase/btr/btr0scrub.cc:151:17: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] storage/innobase/buf/buf0buf.cc:5085:8: warning: nonnull parameter 'bpage' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion] storage/innobase/fil/fil0crypt.cc:2454:5: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] storage/innobase/handler/ha_innodb.cc:18685:7: warning: format specifies type 'unsigned long' but the argument has type 'wsrep_trx_id_t' (aka 'unsigned long long') [-Wformat] storage/innobase/row/row0mysql.cc:3319:5: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] storage/innobase/row/row0mysql.cc:3327:5: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] storage/maria/ma_norec.c:35:10: warning: implicit conversion from 'int' to 'my_bool' (aka 'char') changes value from 131 to -125 [-Wconstant-conversion] storage/maria/ma_norec.c:42:10: warning: implicit conversion from 'int' to 'my_bool' (aka 'char') changes value from 131 to -125 [-Wconstant-conversion] storage/maria/ma_test2.c:1009:12: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat] storage/maria/ma_test2.c:1010:12: warning: format specifies type 'unsigned long' but the argument has type 'size_t' (aka 'unsigned int') [-Wformat] storage/mroonga/ha_mroonga.cpp:9189:44: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand] storage/mroonga/vendor/groonga/lib/expr.c:4987:22: warning: comparison of constant -1 with expression of type 'grn_operator' is always false [-Wtautological-constant-out-of-range-compare] storage/xtradb/btr/btr0scrub.cc:151:17: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] storage/xtradb/buf/buf0buf.cc:5047:8: warning: nonnull parameter 'bpage' will evaluate to 'true' on first encounter [-Wpointer-bool-conversion] storage/xtradb/fil/fil0crypt.cc:2454:5: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] storage/xtradb/row/row0mysql.cc:3324:5: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] storage/xtradb/row/row0mysql.cc:3332:5: warning: format specifies type 'long' but the argument has type 'int' [-Wformat] unittest/sql/mf_iocache-t.cc:120:35: warning: format specifies type 'unsigned long' but the argument has type 'int' [-Wformat] unittest/sql/mf_iocache-t.cc:96:35: note: expanded from macro 'INFO_TAIL'
| | | * | | MDEV-16647 InnoDB fails to drop large temporary table on disconnectMarko Mäkelä2018-08-311-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This regression was introduced in MDEV-16515. We would fail to drop a temporary table on client disconnect, because trx_is_interrupted() would hold. To add insult to injury, in MariaDB 10.1, InnoDB temporary tables are actually persistent, so the garbage temporary tables will never be dropped. row_drop_table_for_mysql(): If several iterations of buf_LRU_drop_page_hash_for_tablespace() are needed, do not interrupt dropping a temporary table even after the transaction was marked as killed. Server shutdown will still terminate the loop, and also DROP TABLE of persistent tables will keep checking if the execution was aborted.
| | * | | | MDEV-12023 Assertion failure sym_node->table != NULL on startupMarko Mäkelä2018-10-301-122/+102
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | row_drop_table_for_mysql(): Avoid accessing non-existing dictionary tables. dict_create_or_check_foreign_constraint_tables(): Add debug instrumentation for creating and dropping a table before the creation of any non-core dictionary tables. trx_purge_add_update_undo_to_history(): Adjust a debug assertion, so that it will not fail due to the test instrumentation.
| | * | | | MDEV-13564: Replace innodb_unsafe_truncate with innodb_safe_truncateMarko Mäkelä2018-10-111-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Rename the 10.2-specific configuration option innodb_unsafe_truncate to innodb_safe_truncate, and invert its value. The default (for now) is innodb_safe_truncate=OFF, to avoid disrupting users with an undo and redo log format change within a Generally Available (GA) release series.
| | * | | | MDEV-13564: Implement innodb_unsafe_truncate=ON for compatibilityMarko Mäkelä2018-10-111-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | While MariaDB Server 10.2 is not really guaranteed to be compatible with Percona XtraBackup 2.4 (for example, the MySQL 5.7 undo log format change that could be present in XtraBackup, but was reverted from MariaDB in MDEV-12289), we do not want to disrupt users who have deployed xtrabackup and MariaDB Server 10.2 in their environments. With this change, MariaDB 10.2 will continue to use the backup-unsafe TRUNCATE TABLE code, so that neither the undo log nor the redo log formats will change in an incompatible way. Undo tablespace truncation will keep using the redo log only. Recovery or backup with old code will fail to shrink the undo tablespace files, but the contents will be recovered just fine. In the MariaDB Server 10.2 series only, we introduce the configuration parameter innodb_unsafe_truncate and make it ON by default. To allow MariaDB Backup (mariabackup) to work properly with TRUNCATE TABLE operations, use loose_innodb_unsafe_truncate=OFF. MariaDB Server 10.3.10 and later releases will always use the backup-safe TRUNCATE TABLE, and this parameter will not be added there. recv_recovery_rollback_active(): Skip row_mysql_drop_garbage_tables() unless innodb_unsafe_truncate=OFF. It is too unsafe to drop orphan tables if RENAME operations are not transactional within InnoDB. LOG_HEADER_FORMAT_10_3: Replaces LOG_HEADER_FORMAT_CURRENT. log_init(), log_group_file_header_flush(), srv_prepare_to_delete_redo_log_files(), innobase_start_or_create_for_mysql(): Choose the redo log format and subformat based on the value of innodb_unsafe_truncate.
* | | | | | MDEV-15662 Instant DROP COLUMN or changing the order of columnsMarko Mäkelä2018-10-191-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Allow ADD COLUMN anywhere in a table, not only adding as the last column. Allow instant DROP COLUMN and instant changing the order of columns. The added columns will always be added last in clustered index records. In new records, instantly dropped columns will be stored as NULL or empty when possible. Information about dropped and reordered columns will be written in a metadata BLOB (mblob), which is stored before the first 'user' field in the hidden metadata record at the start of the clustered index. The presence of mblob is indicated by setting the delete-mark flag in the metadata record. The metadata BLOB stores the number of clustered index fields, followed by an array of column information for each field. For dropped columns, we store the NOT NULL flag, the fixed length, and for variable-length columns, whether the maximum length exceeded 255 bytes. For non-dropped columns, we store the column position. Unlike with MDEV-11369, when a table becomes empty, it cannot be converted back to the canonical format. The reason for this is that other threads may hold cached objects such as row_prebuilt_t::ins_node that could refer to dropped or reordered index fields. For instant DROP COLUMN and ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC, we must store the n_core_null_bytes in the root page, so that the chain of node pointer records can be followed in order to reach the leftmost leaf page where the metadata record is located. If the mblob is present, we will zero-initialize the strings "infimum" and "supremum" in the root page, and use the last byte of "supremum" for storing the number of null bytes (which are allocated but useless on node pointer pages). This is necessary for btr_cur_instant_init_metadata() to be able to navigate to the mblob. If the PRIMARY KEY contains any variable-length column and some nullable columns were instantly dropped, the dict_index_t::n_nullable in the data dictionary could be smaller than it actually is in the non-leaf pages. Because of this, the non-leaf pages could use more bytes for the null flags than the data dictionary expects, and we could be reading the lengths of the variable-length columns from the wrong offset, and thus reading the child page number from wrong place. This is the result of two design mistakes that involve unnecessary storage of data: First, it is nonsense to store any data fields for the leftmost node pointer records, because the comparisons would be resolved by the MIN_REC_FLAG alone. Second, there cannot be any null fields in the clustered index node pointer fields, but we nevertheless reserve space for all the null flags. Limitations (future work): MDEV-17459 Allow instant ALTER TABLE even if FULLTEXT INDEX exists MDEV-17468 Avoid table rebuild on operations on generated columns MDEV-17494 Refuse ALGORITHM=INSTANT when the row size is too large btr_page_reorganize_low(): Preserve any metadata in the root page. Call lock_move_reorganize_page() only after restoring the "infimum" and "supremum" records, to avoid a memcmp() assertion failure. dict_col_t::DROPPED: Magic value for dict_col_t::ind. dict_col_t::clear_instant(): Renamed from dict_col_t::remove_instant(). Do not assert that the column was instantly added, because we sometimes call this unconditionally for all columns. Convert an instantly added column to a "core column". The old name remove_instant() could be mistaken to refer to "instant DROP COLUMN". dict_col_t::is_added(): Rename from dict_col_t::is_instant(). dtype_t::metadata_blob_init(): Initialize the mblob data type. dtuple_t::is_metadata(), dtuple_t::is_alter_metadata(), upd_t::is_metadata(), upd_t::is_alter_metadata(): Check if info_bits refer to a metadata record. dict_table_t::instant: Metadata about dropped or reordered columns. dict_table_t::prepare_instant(): Prepare ha_innobase_inplace_ctx::instant_table for instant ALTER TABLE. innobase_instant_try() will pass this to dict_table_t::instant_column(). On rollback, dict_table_t::rollback_instant() will be called. dict_table_t::instant_column(): Renamed from instant_add_column(). Add the parameter col_map so that columns can be reordered. Copy and adjust v_cols[] as well. dict_table_t::find(): Find an old column based on a new column number. dict_table_t::serialise_columns(), dict_table_t::deserialise_columns(): Convert the mblob. dict_index_t::instant_metadata(): Create the metadata record for instant ALTER TABLE. Invoke dict_table_t::serialise_columns(). dict_index_t::reconstruct_fields(): Invoked by dict_table_t::deserialise_columns(). dict_index_t::clear_instant_alter(): Move the fields for the dropped columns to the end, and sort the surviving index fields in ascending order of column position. ha_innobase::check_if_supported_inplace_alter(): Do not allow adding a FTS_DOC_ID column if a hidden FTS_DOC_ID column exists due to FULLTEXT INDEX. (This always required ALGORITHM=COPY.) instant_alter_column_possible(): Add a parameter for InnoDB table, to check for additional conditions, such as the maximum number of index fields. ha_innobase_inplace_ctx::first_alter_pos: The first column whose position is affected by instant ADD, DROP, or changing the order of columns. innobase_build_col_map(): Skip added virtual columns. prepare_inplace_add_virtual(): Correctly compute num_to_add_vcol. Remove some unnecessary code. Note that the call to innodb_base_col_setup() should be executed later. commit_try_norebuild(): If ctx->is_instant(), let the virtual columns be added or dropped by innobase_instant_try(). innobase_instant_try(): Fill in a zero default value for the hidden column FTS_DOC_ID (to reduce the work needed in MDEV-17459). If any columns were dropped or reordered (or added not last), delete any SYS_COLUMNS records for the following columns, and insert SYS_COLUMNS records for all subsequent stored columns as well as for all virtual columns. If any virtual column is dropped, rewrite all virtual column metadata. Use a shortcut only for adding virtual columns. This is because innobase_drop_virtual_try() assumes that the dropped virtual columns still exist in ctx->old_table. innodb_update_cols(): Renamed from innodb_update_n_cols(). innobase_add_one_virtual(), innobase_insert_sys_virtual(): Change the return type to bool, and invoke my_error() when detecting an error. innodb_insert_sys_columns(): Insert a record into SYS_COLUMNS. Refactored from innobase_add_one_virtual() and innobase_instant_add_col(). innobase_instant_add_col(): Replace the parameter dfield with type. innobase_instant_drop_cols(): Drop matching columns from SYS_COLUMNS and all columns from SYS_VIRTUAL. innobase_add_virtual_try(), innobase_drop_virtual_try(): Let the caller invoke innodb_update_cols(). innobase_rename_column_try(): Skip dropped columns. commit_cache_norebuild(): Update table->fts->doc_col. dict_mem_table_col_rename_low(): Skip dropped columns. trx_undo_rec_get_partial_row(): Skip dropped columns. trx_undo_update_rec_get_update(): Handle the metadata BLOB correctly. trx_undo_page_report_modify(): Avoid out-of-bounds access to record fields. Log metadata records consistently. Apparently, the first fields of a clustered index may be updated in an update_undo vector when the index is ID_IND of SYS_FOREIGN, as part of renaming the table during ALTER TABLE. Normally, updates of the PRIMARY KEY should be logged as delete-mark and an insert. row_undo_mod_parse_undo_rec(), row_purge_parse_undo_rec(): Use trx_undo_metadata. row_undo_mod_clust_low(): On metadata rollback, roll back the root page too. row_undo_mod_clust(): Relax an assertion. The delete-mark flag was repurposed for ALTER TABLE metadata records. row_rec_to_index_entry_impl(): Add the template parameter mblob and the optional parameter info_bits for specifying the desired new info bits. For the metadata tuple, allow conversion between the original format (ADD COLUMN only) and the generic format (with hidden BLOB). Add the optional parameter "pad" to determine whether the tuple should be padded to the index fields (on ALTER TABLE it should), or whether it should remain at its original size (on rollback). row_build_index_entry_low(): Clean up the code, removing redundant variables and conditions. For instantly dropped columns, generate a dummy value that is NULL, the empty string, or a fixed length of NUL bytes, depending on the type of the dropped column. row_upd_clust_rec_by_insert_inherit_func(): On the update of PRIMARY KEY of a record that contained a dropped column whose value was stored externally, we will be inserting a dummy NULL or empty string value to the field of the dropped column. The externally stored column would eventually be dropped when purge removes the delete-marked record for the old PRIMARY KEY value. btr_index_rec_validate(): Recognize the metadata record. btr_discard_only_page_on_level(): Preserve the generic instant ALTER TABLE metadata. btr_set_instant(): Replaces page_set_instant(). This sets a clustered index root page to the appropriate format, or upgrades from the MDEV-11369 instant ADD COLUMN to generic ALTER TABLE format. btr_cur_instant_init_low(): Read and validate the metadata BLOB page before reconstructing the dictionary information based on it. btr_cur_instant_init_metadata(): Do not read any lengths from the metadata record header before reading the BLOB. At this point, we would not actually know how many nullable fields the metadata record contains. btr_cur_instant_root_init(): Initialize n_core_null_bytes in one of two possible ways. btr_cur_trim(): Handle the mblob record. row_metadata_to_tuple(): Convert a metadata record to a data tuple, based on the new info_bits of the metadata record. btr_cur_pessimistic_update(): Invoke row_metadata_to_tuple() if needed. Invoke dtuple_convert_big_rec() for metadata records if the record is too large, or if the mblob is not yet marked as externally stored. btr_cur_optimistic_delete_func(), btr_cur_pessimistic_delete(): When the last user record is deleted, do not delete the generic instant ALTER TABLE metadata record. Only delete MDEV-11369 instant ADD COLUMN metadata records. btr_cur_optimistic_insert(): Avoid unnecessary computation of rec_size. btr_pcur_store_position(): Allow a logically empty page to contain a metadata record for generic ALTER TABLE. REC_INFO_DEFAULT_ROW_ADD: Renamed from REC_INFO_DEFAULT_ROW. This is for the old instant ADD COLUMN (MDEV-11369) only. REC_INFO_DEFAULT_ROW_ALTER: The more generic metadata record, with additional information for dropped or reordered columns. rec_info_bits_valid(): Remove. The only case when this would fail is when the record is the generic ALTER TABLE metadata record. rec_is_alter_metadata(): Check if a record is the metadata record for instant ALTER TABLE (other than ADD COLUMN). NOTE: This function must not be invoked on node pointer records, because the delete-mark flag in those records may be set (it is garbage), and then a debug assertion could fail because index->is_instant() does not necessarily hold. rec_is_add_metadata(): Check if a record is MDEV-11369 ADD COLUMN metadata record (not more generic instant ALTER TABLE). rec_get_converted_size_comp_prefix_low(): Assume that the metadata field will be stored externally. In dtuple_convert_big_rec() during the rec_get_converted_size() call, it would not be there yet. rec_get_converted_size_comp(): Replace status,fields,n_fields with tuple. rec_init_offsets_comp_ordinary(), rec_get_converted_size_comp_prefix_low(), rec_convert_dtuple_to_rec_comp(): Add template<bool mblob = false>. With mblob=true, process a record with a metadata BLOB. rec_copy_prefix_to_buf(): Assert that no fields beyond the key and system columns are being copied. Exclude the metadata BLOB field. rec_convert_dtuple_to_metadata_comp(): Convert an alter metadata tuple into a record. row_upd_index_replace_metadata(): Apply an update vector to an alter_metadata tuple. row_log_allocate(): Replace dict_index_t::is_instant() with a more appropriate condition that ignores dict_table_t::instant. Only a table on which the MDEV-11369 ADD COLUMN was performed can "lose its instantness" when it becomes empty. After instant DROP COLUMN or reordering columns, we cannot simply convert the table to the canonical format, because the data dictionary cache and all possibly existing references to it from other client connection threads would have to be adjusted. row_quiesce_write_index_fields(): Do not crash when the table contains an instantly dropped column. Thanks to Thirunarayanan Balathandayuthapani for discussing the design and implementing an initial prototype of this. Thanks to Matthias Leich for testing.
* | | | | | MDEV-15562: Simplify FOREIGN KEY error handling on DDLMarko Mäkelä2018-10-101-17/+9
|/ / / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The error handling for ALTER TABLE…ALGORITHM=COPY as well as CREATE TABLE used to commit the CREATE TABLE transaction and then issue DROP TABLE in a separate transaction. This is unnecessarily breaking atomicity during DDL operations. Let us revise it so that the DROP TABLE will be executed within the same transaction, which will finally be rolled back. FIXME: Introduce an undo log record so that the data file would be deleted on rollback and no DROP TABLE would be needed at all. FIXME: Avoid unnecessary access to per-table tablespace during DROP TABLE. If the .ibd file is going to be deleted anyway, we should not bother to mark the pages free. dict_create_add_foreigns_to_dictionary(): Do not commit the transaction. We want simple rollback in case dict_load_foreigns() would fail. create_table_info_t::create_table(), row_create_index_for_mysql(), row_table_add_foreign_constraints(): Before invoking rollback, drop the table. Rollback would invoke trx_t::evict_table(), and after that dropping the table would be a no-op. ha_innobase::create(): Before rollback, drop the table. If the SQL layer invoked ha_innobase::delete_table() later, it would be a no-op because the rollback would have invoked trx_t::evict_table().
* | | | | MDEV-17158 TRUNCATE is not atomic after MDEV-13564Marko Mäkelä2018-09-101-11/+14
|\ \ \ \ \ | |/ / / /
| * | | | MDEV-17158 TRUNCATE is not atomic after MDEV-13564Marko Mäkelä2018-09-101-14/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | It turned out that ha_innobase::truncate() would prematurely commit the transaction already before the completion of the ha_innobase::create(). All of this must be atomic. innodb.truncate_crash: Use the correct DEBUG_SYNC point, and tolerate non-truncation of the table, because the redo log for the TRUNCATE transaction commit might be flushed due to some InnoDB background activity. dict_build_tablespace_for_table(): Merge to the function dict_build_table_def_step(). dict_build_table_def_step(): If a table is being created during an already started data dictionary transaction (such as TRUNCATE), persistently write the table_id to the undo log header before creating any file. In this way, the recovery of TRUNCATE will be able to delete the new file before rolling back the rename of the original table. dict_table_rename_in_cache(): Add the parameter replace_new_file, used as part of rolling back a TRUNCATE operation. fil_rename_tablespace_check(): Add the parameter replace_new. If the parameter is set and a file identified by new_path exists, remove a possible tablespace and also the file. create_table_info_t::create_table_def(): Remove some debug assertions that no longer hold. During TRUNCATE, the transaction will already have been started (and performed a rename operation) before the table is created. Also, remove a call to dict_build_tablespace_for_table(). create_table_info_t::create_table(): Add the parameter create_fk=true. During TRUNCATE TABLE, do not add FOREIGN KEY constraints to the InnoDB data dictionary, because they will also not be removed. row_table_add_foreign_constraints(): If trx=NULL, do not modify the InnoDB data dictionary, but only load the FOREIGN KEY constraints from the data dictionary. ha_innobase::create(): Lock the InnoDB data dictionary cache only if no transaction was passed by the caller. Unlock it in any case. innobase_rename_table(): Add the parameter commit = true. If !commit, do not lock or unlock the data dictionary cache. ha_innobase::truncate(): Lock the data dictionary before invoking rename or create, and let ha_innobase::create() unlock it and also commit or roll back the transaction. trx_undo_mark_as_dict(): Renamed from trx_undo_mark_as_dict_operation() and declared global instead of static. row_undo_ins_parse_undo_rec(): If table_id is set, this must be rolling back the rename operation in TRUNCATE TABLE, and therefore replace_new_file=true.
* | | | | Follow-up to MDEV-13407: Remove fil_wait_crypt_bg_threads()Marko Mäkelä2018-09-091-33/+0
|\ \ \ \ \ | |/ / / /
| * | | | Follow-up to MDEV-13407: Remove fil_wait_crypt_bg_threads()Marko Mäkelä2018-09-091-34/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Tables whose reference count is not zero will be crash-safely dropped in the background when the count reaches zero. Therefore, it is no longer necessary to wait for all references to be released before possibly adding the table to the background queue.
* | | | | MDEV-13564 Mariabackup does not work with TRUNCATEMarko Mäkelä2018-09-071-53/+86
|\ \ \ \ \ | |/ / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is a merge from 10.2, but the 10.2 version of this will not be pushed into 10.2 yet, because the 10.2 version would include backports of MDEV-14717 and MDEV-14585, which would introduce a crash recovery regression: Tables could be lost on table-rebuilding DDL operations, such as ALTER TABLE, OPTIMIZE TABLE or this new backup-friendly TRUNCATE TABLE. The test innodb.truncate_crash occasionally loses the table due to the following bug: MDEV-17158 log_write_up_to() sometimes fails
| * | | | MDEV-14585 Automatically remove #sql- tables in InnoDB dictionary during ↵Marko Mäkelä2018-09-071-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | recovery This is a backport of the following commits: commit b4165985c97a4133e19dd99b459dea27f87fbb1b commit 69e88de0fe6dc5312f5d6e7a179a5ab73d60dc43 commit 40f4525f43aba5d579cf55bae2df504001cd04f4 commit 656f66def27b7a2cf42a28f873f1eeef0416aa71 Now that MDEV-14717 made RENAME TABLE crash-safe within InnoDB, it should be safe to drop the #sql- tables within InnoDB during crash recovery. These tables can be one of two things: (1) #sql-ib related to deferred DROP TABLE (follow-up to MDEV-13407) or to table-rebuilding ALTER TABLE...ALGORITHM=INPLACE (since MDEV-14378, only related to the intermediate copy of a table), (2) #sql- related to the intermediate copy of a table during ALTER TABLE...ALGORITHM=COPY We will not drop tables whose name starts with #sql2, because the server can be killed during an ALGORITHM=COPY operation at a point where the original table was renamed to #sql2 but the finished intermediate copy was not yet renamed from #sql- to the original table name. If an old version of MariaDB Server before 10.2.13 (MDEV-11415) was killed while ALTER TABLE...ALGORITHM=COPY was in progress, after recovery there could be undo log records for some records that were inserted into an intermediate copy of the table. Due to these undo log records, InnoDB would resurrect locks at recovery, and the intermediate table would be locked while we are trying to drop it. This would cause a call to row_rename_table_for_mysql(), either from row_mysql_drop_garbage_tables() or from the rollback of a RENAME operation that was part of the ALTER TABLE. row_rename_table_for_mysql(): Do not attempt to parse FOREIGN KEY constraints when renaming from #sql-something to #sql-something-else, because it does not make any sense. row_drop_table_for_mysql(): When deferring DROP TABLE due to locks, do not rename the table if its name already starts with the #sql- prefix, which is what row_mysql_drop_garbage_tables() uses. Previously, the too strict prefix #sql-ib was used, and some tables were renamed unnecessarily.
| * | | | Follow-up to MDEV-13407 innodb.drop_table_background failed in buildbot with ↵Marko Mäkelä2018-09-071-51/+95
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | "Tablespace for table exists" This is a backport of commit 88aff5f471d3d9ae8ecc2f909bcf5bd0ddd6aa7c. The InnoDB background DROP TABLE queue is something that we should really remove, but are unable to until we remove dict_operation_lock so that DDL and DML operations can be combined in a single transaction. Because the queue is not persistent, it is not crash-safe. We should in some way ensure that the deferred-dropped tables will be dropped after server restart. The existence of two separate transactions complicates the error handling of CREATE TABLE...SELECT. We should really not break locks in DROP TABLE. Our solution to these problems is to rename the table to a temporary name, and to drop such-named tables on InnoDB startup. Also, the queue will use table IDs instead of names from now on. check-testcase.test: Ignore #sql-ib*.ibd files, because tables may enter the background DROP TABLE queue shortly before the test finishes. innodb.drop_table_background: Test CREATE...SELECT and the creation of tables whose file name starts with #sql-ib. innodb.alter_crash: Adjust the recovery, now that the #sql-ib tables will be dropped on InnoDB startup. row_mysql_drop_garbage_tables(): New function, to drop all #sql-ib tables on InnoDB startup. row_drop_table_for_mysql_in_background(): Remove an unnecessary and misplaced call to log_buffer_flush_to_disk(). (The call should have been after the transaction commit. We do not care about flushing the redo log here, because the table would be dropped again at server startup.) Remove the entry from the list after the table no longer exists. If server shutdown has been initiated, empty the list without actually dropping any tables. They will be dropped again on startup. row_drop_table_for_mysql(): Do not call lock_remove_all_on_table(). Instead, if locks exist, defer the DROP TABLE until they do not exist. If the table name does not start with #sql-ib, rename it to that prefix before adding it to the background DROP TABLE queue.