summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-08-02 17:35:24 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-08-03 08:33:38 +0300
commitde469a2f297b02c169d43ac1f6a0a6f63a913a81 (patch)
tree43449df185fe7efc5cfc2c225348d80abc1d8250 /scripts
parent204608974536a99e0c218b909b7137395ab8cd22 (diff)
downloadmariadb-git-de469a2f297b02c169d43ac1f6a0a6f63a913a81.tar.gz
MDEV-14637: Fix hang due to persistent statistics
Similar to the tables SYS_FOREIGN and SYS_FOREIGN_COLS, the tables mysql.innodb_table_stats and mysql.innodb_index_stats are updated by the InnoDB internal SQL parser, which fails to enforce the size limits of the data. Due to this, it is possible for InnoDB to hang when there are persistent statistics defined on partitioned tables where the total length of table name, partition name and subpartition name exceeds the incorrectly defined limit VARCHAR(64). That column should have been defined as VARCHAR(199). btr_node_ptr_max_size(): Interpret the VARCHAR(64) as VARCHAR(199), to prevent a hang in the case that the upgrade script has not been run. dict_table_schema_check(): Ignore difference in the length of the table_name column. ha_innobase::max_supported_key_length(): For innodb_page_size=4k, return a larger value so that the table mysql.innodb_index_stats can be created. This could allow "impossible" tables to be created, such that it is not possible to insert anything into a secondary index when both the secondary key and the primary key are long, but this is the easiest and most consistent way. The Oracle fix would only ignore the maximum length violation for the two statistics tables. os_file_get_status_posix(), os_file_get_status_win32(): Handle ENAMETOOLONG as well. This patch is based on the following change in MySQL 5.7.23. Not all changes were applied, and our variant allows persistent statistics to work without hangs even if the table definitions were not upgraded. From fdbdce701ab8145ae234c9d401109dff4e4106cb Mon Sep 17 00:00:00 2001 From: Aditya A <aditya.a@oracle.com> Date: Thu, 17 May 2018 16:11:43 +0530 Subject: [PATCH] Bug #26390736 THE FIELD TABLE_NAME (VARCHAR(64)) FROM MYSQL.INNODB_TABLE_STATS CAN OVERFLOW. In mysql.innodb_index_stats and mysql.innodb_table_stats tables the table name column didn't take into consideration partition names which can be more than varchar(64).
Diffstat (limited to 'scripts')
-rw-r--r--scripts/mysql_system_tables.sql6
-rw-r--r--scripts/mysql_system_tables_fix.sql6
2 files changed, 6 insertions, 6 deletions
diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql
index 7b614163f46..c5792168213 100644
--- a/scripts/mysql_system_tables.sql
+++ b/scripts/mysql_system_tables.sql
@@ -1,4 +1,4 @@
--- Copyright (c) 2007, 2013, Oracle and/or its affiliates.
+-- Copyright (c) 2007, 2018, Oracle and/or its affiliates.
-- Copyright (c) 2008, 2014, Monty Program Ab & SkySQL Ab
--
-- This program is free software; you can redistribute it and/or modify
@@ -105,7 +105,7 @@ CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_b
SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats (
database_name VARCHAR(64) NOT NULL,
- table_name VARCHAR(64) NOT NULL,
+ table_name VARCHAR(199) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
n_rows BIGINT UNSIGNED NOT NULL,
clustered_index_size BIGINT UNSIGNED NOT NULL,
@@ -115,7 +115,7 @@ SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats (
SET @create_innodb_index_stats="CREATE TABLE IF NOT EXISTS innodb_index_stats (
database_name VARCHAR(64) NOT NULL,
- table_name VARCHAR(64) NOT NULL,
+ table_name VARCHAR(199) NOT NULL,
index_name VARCHAR(64) NOT NULL,
last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
/* there are at least:
diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql
index e724c3e2d23..db32834c4d6 100644
--- a/scripts/mysql_system_tables_fix.sql
+++ b/scripts/mysql_system_tables_fix.sql
@@ -697,13 +697,13 @@ set @str=replace(@str, "innodb_index_stats", "innodb_table_stats");
prepare stmt from @str;
execute stmt;
-# update timestamp fields in the innodb stat tables
-set @str="alter table mysql.innodb_index_stats modify last_update timestamp not null default current_timestamp on update current_timestamp";
+# update table_name and timestamp fields in the innodb stat tables
+set @str="alter table mysql.innodb_index_stats modify last_update timestamp not null default current_timestamp on update current_timestamp, modify table_name varchar(199)";
set @str=if(@have_innodb <> 0, @str, "set @dummy = 0");
prepare stmt from @str;
execute stmt;
-set @str="alter table mysql.innodb_table_stats modify last_update timestamp not null default current_timestamp on update current_timestamp";
+set @str="alter table mysql.innodb_table_stats modify last_update timestamp not null default current_timestamp on update current_timestamp, modify table_name varchar(199)";
set @str=if(@have_innodb <> 0, @str, "set @dummy = 0");
prepare stmt from @str;
execute stmt;