summaryrefslogtreecommitdiff
path: root/mysql-test
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-04-16 16:35:21 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-04-16 17:21:17 +0300
commitd9d79e4d015e8fb7d4a439dca531235c8b26ca3d (patch)
tree91124b9da65c72b32c2f622d878b8d7855233e64 /mysql-test
parentf66e006b08434e8b5e14ae5ffdede8c605646d6b (diff)
downloadmariadb-git-d9d79e4d015e8fb7d4a439dca531235c8b26ca3d.tar.gz
MDEV-17494 Refuse ALGORITHM=INSTANT when the row size is too large
With the MDEV-15562 instant DROP COLUMN, clustered index records will contain traces of dropped columns, as follows: In ROW_FORMAT=REDUNDANT, dropped columns will be stored as 0 bytes, but they will consume 1 or 2 bytes per column in the record header. In ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC, dropped columns will be stored as NULL if allowed. This will consume 1 bit per nullable column. In ROW_FORMAT=COMPACT or ROW_FORMAT=DYNAMIC, dropped NOT NULL columns will be stored as 0 bytes if allowed. This will consume 1 byte per NOT NULL variable-length column. Fixed-length columns will be stored using the fixed number of bytes. The metadata record will be 20 bytes larger than user records, because it will contain a metadata BLOB pointer. We must refuse ALGORITHM=INSTANT (and require a table rebuild) if the metadata record would grow too big to fit in the index page. If SQL_MODE includes STRICT_TRANS_TABLES or STRICT_ALL_TABLES, we should refuse ALGORITHM=INSTANT if the maximum length of user records would exceed the maximum size of an index page, similar to what row_create_index_for_mysql() does during CREATE TABLE. This limit would kick in when the default values for any instantly added columns in the metadata record are NULL or short, but the allowed maximum values are long. instant_alter_column_possible(): Add the parameter "bool strict" to enable checks for the user record size, and always check the metadata record size.
Diffstat (limited to 'mysql-test')
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff9
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff9
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff9
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff9
-rw-r--r--mysql-test/suite/innodb/r/instant_alter_limit.result11
-rw-r--r--mysql-test/suite/innodb/t/instant_alter_limit.test20
6 files changed, 66 insertions, 1 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff
new file mode 100644
index 00000000000..5e46c66ce73
--- /dev/null
+++ b/mysql-test/suite/innodb/r/instant_alter_limit,32k.rdiff
@@ -0,0 +1,9 @@
+--- instant_alter_limit.result
++++ instant_alter_limit.result
+@@ -42,5 +42,5 @@
+ FROM information_schema.global_status
+ WHERE variable_name = 'innodb_instant_alter_column';
+ instants
+-502
++506
+ DROP TABLE t;
diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff
new file mode 100644
index 00000000000..795116ffae4
--- /dev/null
+++ b/mysql-test/suite/innodb/r/instant_alter_limit,4k.rdiff
@@ -0,0 +1,9 @@
+--- instant_alter_limit.result
++++ instant_alter_limit.result
+@@ -42,5 +42,5 @@
+ FROM information_schema.global_status
+ WHERE variable_name = 'innodb_instant_alter_column';
+ instants
+-502
++474
+ DROP TABLE t;
diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff
new file mode 100644
index 00000000000..5e46c66ce73
--- /dev/null
+++ b/mysql-test/suite/innodb/r/instant_alter_limit,64k.rdiff
@@ -0,0 +1,9 @@
+--- instant_alter_limit.result
++++ instant_alter_limit.result
+@@ -42,5 +42,5 @@
+ FROM information_schema.global_status
+ WHERE variable_name = 'innodb_instant_alter_column';
+ instants
+-502
++506
+ DROP TABLE t;
diff --git a/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff b/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff
new file mode 100644
index 00000000000..37d2ae67c4e
--- /dev/null
+++ b/mysql-test/suite/innodb/r/instant_alter_limit,8k.rdiff
@@ -0,0 +1,9 @@
+--- instant_alter_limit.result
++++ instant_alter_limit.result
+@@ -42,5 +42,5 @@
+ FROM information_schema.global_status
+ WHERE variable_name = 'innodb_instant_alter_column';
+ instants
+-502
++492
+ DROP TABLE t;
diff --git a/mysql-test/suite/innodb/r/instant_alter_limit.result b/mysql-test/suite/innodb/r/instant_alter_limit.result
index e66579e4a94..e169c40d462 100644
--- a/mysql-test/suite/innodb/r/instant_alter_limit.result
+++ b/mysql-test/suite/innodb/r/instant_alter_limit.result
@@ -32,4 +32,15 @@ instants
SELECT * FROM t;
a b
1 0
+ALTER TABLE t ADD COLUMN (c CHAR(255) NOT NULL, d BIGINT NOT NULL),
+ALGORITHM=INSTANT;
+UPDATE t SET b=b+1,d=d+1,c='foo';
+SELECT * FROM t;
+a b c d
+1 1 foo 1
+SELECT variable_value-@old_instant instants
+FROM information_schema.global_status
+WHERE variable_name = 'innodb_instant_alter_column';
+instants
+502
DROP TABLE t;
diff --git a/mysql-test/suite/innodb/t/instant_alter_limit.test b/mysql-test/suite/innodb/t/instant_alter_limit.test
index ded14eee89b..b50a1b15295 100644
--- a/mysql-test/suite/innodb/t/instant_alter_limit.test
+++ b/mysql-test/suite/innodb/t/instant_alter_limit.test
@@ -1,4 +1,4 @@
---source include/have_innodb.inc
+--source include/innodb_page_size.inc
SET @old_instant=
(SELECT variable_value FROM information_schema.global_status
@@ -38,5 +38,23 @@ FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
SELECT * FROM t;
+ALTER TABLE t ADD COLUMN (c CHAR(255) NOT NULL, d BIGINT NOT NULL),
+ALGORITHM=INSTANT;
+
+--disable_query_log
+let $n=253;
+while ($n) {
+dec $n;
+ALTER TABLE t DROP b, DROP c, DROP d,
+ADD COLUMN (b INT NOT NULL, c CHAR(255) NOT NULL, d BIGINT NOT NULL);
+}
+--enable_query_log
+
+UPDATE t SET b=b+1,d=d+1,c='foo';
+SELECT * FROM t;
+
+SELECT variable_value-@old_instant instants
+FROM information_schema.global_status
+WHERE variable_name = 'innodb_instant_alter_column';
DROP TABLE t;