MDEV-33462 Server aborts while altering an InnoDB statistics table

Problem:
=======
- When online alter of InnoDB statistics table happens,
any transaction which updates the statistics table
has to read the undo log and log the DML changes during
transaction commit. Applying undo log
(UndorecApplier::apply_undo_rec) requires a shared
lock on dictionary cache but dict_stats_save() already
holds write lock on dictionary cache. This leads to
abort of server during commit of statistics table changes.

Solution:
========
- Disallow LOCK=NONE operation for the InnoDB statistics table.
The reasoning is that statistics tables are typically
rather small, so any blocking would be rather short.
Writes to the statistics tables should be a rare operation.
parent 042c3fc4
......@@ -174,3 +174,10 @@ SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5;
DROP TABLE t1;
#
# MDEV-33462 Disallow LOCK=NONE operation on statistics table
#
ALTER TABLE mysql.innodb_table_stats FORCE, LOCK=NONE;
ERROR 0A000: LOCK=NONE is not supported. Reason: innodb_table_stats. Try LOCK=SHARED
ALTER TABLE mysql.innodb_index_stats FORCE, LOCK=NONE;
ERROR 0A000: LOCK=NONE is not supported. Reason: innodb_index_stats. Try LOCK=SHARED
......@@ -96,3 +96,11 @@ SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5;
DROP TABLE t1;
--echo #
--echo # MDEV-33462 Disallow LOCK=NONE operation on statistics table
--echo #
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE mysql.innodb_table_stats FORCE, LOCK=NONE;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE mysql.innodb_index_stats FORCE, LOCK=NONE;
......@@ -2815,6 +2815,14 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
if (m_prebuilt->table->is_stats_table()) {
if (ha_alter_info->online) {
ha_alter_info->unsupported_reason =
table_share->table_name.str;
}
online= false;
}
// FIXME: implement Online DDL for system-versioned operations
if (ha_alter_info->handler_flags & INNOBASE_ALTER_VERSIONED_REBUILD) {
if (ha_alter_info->online) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment