[Commits] 4f0dabe: MDEV-9040: 10.1.8 fails after upgrade from 10.0.21

Jan Lindström jan.lindstrom at mariadb.com
Thu Nov 5 09:50:01 EET 2015


revision-id: 4f0dabedd806a28410aa280bb714f767679a6480 (mariadb-10.1.8-25-g4f0dabe)
parent(s): 95289e5b665d6a3e37f938d0db978d0d0166e493
committer: Jan Lindström
timestamp: 2015-11-05 09:42:23 +0200
message:

MDEV-9040: 10.1.8 fails after upgrade from 10.0.21

Analysis: Lengths which are not UNIV_SQL_NULL, but bigger than the following
number indicate that a field contains a reference to an externally
stored part of the field in the tablespace. The length field then
contains the sum of the following flag and the locally stored len.

This was incorrectly set to

define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_MAX)

When it should be

define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_DEF)

Additionally, we need to disable support for > 16K page size for
row compressed tables because a compressed page directory entry
reserves 14 bits for the start offset and 2 bits for flags.
This limits the uncompressed page size to 16k. To support
larger pages page directory entry needs to be larger.

---
 mysql-test/suite/innodb/r/innodb-32k.result        | 48 ++---------------
 mysql-test/suite/innodb/r/innodb-64k.result        | 23 ++------
 .../innodb/r/innodb-change-buffer-recovery.result  |  3 ++
 .../suite/innodb/r/innodb_blob_truncate.result     | 19 +++++++
 mysql-test/suite/innodb/t/innodb-32k-master.opt    |  4 +-
 mysql-test/suite/innodb/t/innodb-32k.test          | 62 ++--------------------
 mysql-test/suite/innodb/t/innodb-64k-master.opt    |  4 +-
 mysql-test/suite/innodb/t/innodb-64k.test          | 30 ++---------
 .../innodb/t/innodb-change-buffer-recovery.test    |  3 ++
 .../suite/innodb/t/innodb_blob_truncate.test       | 45 ++++++++++++++++
 mysql-test/suite/sys_vars/r/sysvars_innodb.result  |  2 +-
 storage/innobase/btr/btr0cur.cc                    |  6 +++
 storage/innobase/fil/fil0fil.cc                    | 13 +++--
 storage/innobase/handler/ha_innodb.cc              | 33 +++++++++++-
 storage/innobase/include/fsp0types.h               | 18 +++++--
 storage/innobase/include/rem0rec.h                 |  2 +-
 storage/innobase/include/univ.i                    |  8 ++-
 storage/innobase/page/page0zip.cc                  |  4 +-
 storage/innobase/row/row0ftsort.cc                 |  2 +-
 storage/xtradb/btr/btr0cur.cc                      |  6 +++
 storage/xtradb/fil/fil0fil.cc                      | 13 +++--
 storage/xtradb/handler/ha_innodb.cc                | 33 +++++++++++-
 storage/xtradb/include/fsp0types.h                 | 18 +++++--
 storage/xtradb/include/rem0rec.h                   |  2 +-
 storage/xtradb/include/univ.i                      |  6 +--
 storage/xtradb/page/page0zip.cc                    |  4 +-
 storage/xtradb/row/row0ftsort.cc                   |  2 +-
 27 files changed, 222 insertions(+), 191 deletions(-)

diff --git a/mysql-test/suite/innodb/r/innodb-32k.result b/mysql-test/suite/innodb/r/innodb-32k.result
index 25496f5..2253ba5 100644
--- a/mysql-test/suite/innodb/r/innodb-32k.result
+++ b/mysql-test/suite/innodb/r/innodb-32k.result
@@ -1,4 +1,7 @@
 call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *");
+call mtr.add_suppression("InnoDB: Resizing redo log from *");
+call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files.");
+call mtr.add_suppression("InnoDB: New log files created, LSN=*");
 SET GLOBAL innodb_file_format = `Barracuda`;
 SET GLOBAL innodb_file_per_table = ON;
 # Test 1) Show the page size from Information Schema
@@ -109,29 +112,9 @@ c61 char(200), c62 char(200), c63 char(200), c64 char(200), c65 char(200),
 c66 char(200), c67 char(200), c68 char(200), c69 char(200), c70 char(200),
 c71 char(200), c72 char(200), c73 char(200), c74 char(200), c75 char(200),
 c76 char(200), c77 char(200), c78 char(200), c79 char(200), c80 char(200),
-c81 char(62)
-) ROW_FORMAT=compressed;
-ERROR 42000: Row size too large (> max_row_size). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
-CREATE TABLE t1 (
-c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
-c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200),
-c11 char(200), c12 char(200), c13 char(200), c14 char(200), c15 char(200),
-c16 char(200), c17 char(200), c18 char(200), c19 char(200), c20 char(200),
-c21 char(200), c22 char(200), c23 char(200), c24 char(200), c25 char(200),
-c26 char(200), c27 char(200), c28 char(200), c29 char(200), c30 char(200),
-c31 char(200), c32 char(200), c33 char(200), c34 char(200), c35 char(200),
-c36 char(200), c37 char(200), c38 char(200), c39 char(200), c40 char(200),
-c41 char(200), c42 char(200), c43 char(200), c44 char(200), c45 char(200),
-c46 char(200), c47 char(200), c48 char(200), c49 char(200), c50 char(200),
-c51 char(200), c52 char(200), c53 char(200), c54 char(200), c55 char(200),
-c56 char(200), c57 char(200), c58 char(200), c59 char(200), c60 char(200),
-c61 char(200), c62 char(200), c63 char(200), c64 char(200), c65 char(200),
-c66 char(200), c67 char(200), c68 char(200), c69 char(200), c70 char(200),
-c71 char(200), c72 char(200), c73 char(200), c74 char(200), c75 char(200),
-c76 char(200), c77 char(200), c78 char(200), c79 char(200), c80 char(200),
 c81 char(63)
 ) ROW_FORMAT=compressed;
-ERROR 42000: Row size too large (> max_row_size). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
+ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options")
 CREATE TABLE t1 (
 c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
 c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200),
@@ -428,29 +411,6 @@ UPDATE t3 SET c = REPEAT('b',32800);
 SHOW WARNINGS;
 Level	Code	Message
 DROP TABLE t3;
-SET SESSION innodb_strict_mode = off;
-CREATE TABLE t1(
-c text NOT NULL, d text NOT NULL,
-PRIMARY KEY (c(767),d(767)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
-ERROR 42000: Row size too large (> 16318). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
-CREATE TABLE t1(
-c text NOT NULL, d text NOT NULL,
-PRIMARY KEY (c(767),d(767)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2 CHARSET=ASCII;
-ERROR 42000: Row size too large (> 16318). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
-CREATE TABLE t1(
-c text NOT NULL, d text NOT NULL,
-PRIMARY KEY (c(767),d(767)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 CHARSET=ASCII;
-drop table t1;
-CREATE TABLE t1(c text, PRIMARY KEY (c(440)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
-ERROR 42000: Row size too large (> 16318). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
-CREATE TABLE t1(c text, PRIMARY KEY (c(438)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
-INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
-DROP TABLE t1;
 DROP TABLE t1_purge, t2_purge, t3_purge, t4_purge;
 DROP TABLE tlong;
 DROP TABLE tlong2;
diff --git a/mysql-test/suite/innodb/r/innodb-64k.result b/mysql-test/suite/innodb/r/innodb-64k.result
index 3578d0a..c84ad8c 100644
--- a/mysql-test/suite/innodb/r/innodb-64k.result
+++ b/mysql-test/suite/innodb/r/innodb-64k.result
@@ -1,4 +1,7 @@
 call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *");
+call mtr.add_suppression("InnoDB: Resizing redo log from *");
+call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files.");
+call mtr.add_suppression("InnoDB: New log files created, LSN=*");
 SET GLOBAL innodb_file_format = `Barracuda`;
 SET GLOBAL innodb_file_per_table = ON;
 # Test 1) Show the page size from Information Schema
@@ -230,26 +233,6 @@ c190 char(200), c191 char(200), c192 char(100),
 c81 char(157)
 ) ROW_FORMAT=dynamic;
 ERROR 42000: Row size too large (> max_row_size). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
-CREATE TABLE t1 (
-c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
-c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200),
-c11 char(200), c12 char(200), c13 char(200), c14 char(200), c15 char(200),
-c16 char(200), c17 char(200), c18 char(200), c19 char(200), c20 char(200),
-c21 char(200), c22 char(200), c23 char(200), c24 char(200), c25 char(200),
-c26 char(200), c27 char(200), c28 char(200), c29 char(200), c30 char(200),
-c31 char(200), c32 char(200), c33 char(200), c34 char(200), c35 char(200),
-c36 char(200), c37 char(200), c38 char(200), c39 char(200), c40 char(200),
-c41 char(200), c42 char(200), c43 char(200), c44 char(200), c45 char(200),
-c46 char(200), c47 char(200), c48 char(200), c49 char(200), c50 char(200),
-c51 char(200), c52 char(200), c53 char(200), c54 char(200), c55 char(200),
-c56 char(200), c57 char(200), c58 char(200), c59 char(200), c60 char(200),
-c61 char(200), c62 char(200), c63 char(200), c64 char(200), c65 char(200),
-c66 char(200), c67 char(200), c68 char(200), c69 char(200), c70 char(200),
-c71 char(200), c72 char(200), c73 char(200), c74 char(200), c75 char(200),
-c76 char(200), c77 char(200), c78 char(200), c79 char(200), c80 char(200),
-c81 char(62)
-) ROW_FORMAT=compressed;
-ERROR 42000: Row size too large (> max_row_size). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
 # Test 8) Test creating a table that could lead to undo log overflow.
 CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob,
 h blob,i blob,j blob,k blob,l blob,m blob,n blob,
diff --git a/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result b/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result
index 07e1300..96d2a3d 100644
--- a/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result
+++ b/mysql-test/suite/innodb/r/innodb-change-buffer-recovery.result
@@ -21,6 +21,9 @@ INSERT INTO t1 SELECT 0,b,c FROM t1;
 INSERT INTO t1 SELECT 0,b,c FROM t1;
 INSERT INTO t1 SELECT 0,b,c FROM t1;
 INSERT INTO t1 SELECT 0,b,c FROM t1;
+INSERT INTO t1 SELECT 0,b,c FROM t1;
+INSERT INTO t1 SELECT 0,b,c FROM t1;
+INSERT INTO t1 SELECT 0,b,c FROM t1;
 BEGIN;
 SELECT b FROM t1 LIMIT 3;
 b
diff --git a/mysql-test/suite/innodb/r/innodb_blob_truncate.result b/mysql-test/suite/innodb/r/innodb_blob_truncate.result
new file mode 100644
index 0000000..569e6b0
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_blob_truncate.result
@@ -0,0 +1,19 @@
+SET GLOBAL innodb_file_format = `Barracuda`;
+SET GLOBAL innodb_file_per_table = ON;
+create table t1(a blob) engine=innodb key_block_size=8;
+create function generate_blob()
+returns varchar(20000)
+begin
+declare x varchar(20000) default '';
+declare i int default 500;
+while i > 0 do
+set x = concat(sha1(i), x);
+set i = i - 1;
+end while;
+return x;
+end //
+insert into t1 select generate_blob();
+truncate t1;
+insert into t1 select generate_blob();
+drop table t1;
+drop function generate_blob;
diff --git a/mysql-test/suite/innodb/t/innodb-32k-master.opt b/mysql-test/suite/innodb/t/innodb-32k-master.opt
index 3a0fcd4..ef27bc1 100644
--- a/mysql-test/suite/innodb/t/innodb-32k-master.opt
+++ b/mysql-test/suite/innodb/t/innodb-32k-master.opt
@@ -1 +1,3 @@
---default_storage_engine=InnoDB --innodb-buffer-pool-size=24M
+--default_storage_engine=InnoDB
+--innodb-buffer-pool-size=24M
+--innodb-log-file-size=32M
diff --git a/mysql-test/suite/innodb/t/innodb-32k.test b/mysql-test/suite/innodb/t/innodb-32k.test
index 039c4d2..65c1d4b 100644
--- a/mysql-test/suite/innodb/t/innodb-32k.test
+++ b/mysql-test/suite/innodb/t/innodb-32k.test
@@ -4,6 +4,9 @@
 --source include/have_innodb_32k.inc
 
 call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *");
+call mtr.add_suppression("InnoDB: Resizing redo log from *");
+call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files.");
+call mtr.add_suppression("InnoDB: New log files created, LSN=*");
 
 --disable_query_log
 let $MYSQLD_DATADIR= `select @@datadir`;
@@ -119,32 +122,8 @@ c76 char(200), c77 char(200), c78 char(200), c79 char(200), c80 char(200),
 c81 char(200), c82 char(83)
 ) ROW_FORMAT=compact;
 
-# Compressed table; 16063 bytes with 81 CHAR fields
-
 --replace_regex /> [0-9]*/> max_row_size/
---error ER_TOO_BIG_ROWSIZE
-CREATE TABLE t1 (
-c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
-c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200),
-c11 char(200), c12 char(200), c13 char(200), c14 char(200), c15 char(200),
-c16 char(200), c17 char(200), c18 char(200), c19 char(200), c20 char(200),
-c21 char(200), c22 char(200), c23 char(200), c24 char(200), c25 char(200),
-c26 char(200), c27 char(200), c28 char(200), c29 char(200), c30 char(200),
-c31 char(200), c32 char(200), c33 char(200), c34 char(200), c35 char(200),
-c36 char(200), c37 char(200), c38 char(200), c39 char(200), c40 char(200),
-c41 char(200), c42 char(200), c43 char(200), c44 char(200), c45 char(200),
-c46 char(200), c47 char(200), c48 char(200), c49 char(200), c50 char(200),
-c51 char(200), c52 char(200), c53 char(200), c54 char(200), c55 char(200),
-c56 char(200), c57 char(200), c58 char(200), c59 char(200), c60 char(200),
-c61 char(200), c62 char(200), c63 char(200), c64 char(200), c65 char(200),
-c66 char(200), c67 char(200), c68 char(200), c69 char(200), c70 char(200),
-c71 char(200), c72 char(200), c73 char(200), c74 char(200), c75 char(200),
-c76 char(200), c77 char(200), c78 char(200), c79 char(200), c80 char(200),
-c81 char(62)
-) ROW_FORMAT=compressed;
-
---replace_regex /> [0-9]*/> max_row_size/
---error ER_TOO_BIG_ROWSIZE
+--error 1005
 CREATE TABLE t1 (
 c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
 c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200),
@@ -505,39 +484,6 @@ UPDATE t3 SET c = REPEAT('b',32800);
 SHOW WARNINGS;
 DROP TABLE t3;
 
-# The following should fail in non-strict mode too.
-
-SET SESSION innodb_strict_mode = off;
---error ER_TOO_BIG_ROWSIZE
-CREATE TABLE t1(
-	c text NOT NULL, d text NOT NULL,
-	PRIMARY KEY (c(767),d(767)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
-
---error ER_TOO_BIG_ROWSIZE
-CREATE TABLE t1(
-	c text NOT NULL, d text NOT NULL,
-	PRIMARY KEY (c(767),d(767)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2 CHARSET=ASCII;
-
-CREATE TABLE t1(
-	c text NOT NULL, d text NOT NULL,
-	PRIMARY KEY (c(767),d(767)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 CHARSET=ASCII;
-
-drop table t1;
-
---error ER_TOO_BIG_ROWSIZE
-CREATE TABLE t1(c text, PRIMARY KEY (c(440)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
-
-CREATE TABLE t1(c text, PRIMARY KEY (c(438)))
-ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
-
-INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
-
-DROP TABLE t1;
-
 # The tests that uses these tables required the purge thread to run.
 # Just in case it has not by now, provide a 10 second wait.
 
diff --git a/mysql-test/suite/innodb/t/innodb-64k-master.opt b/mysql-test/suite/innodb/t/innodb-64k-master.opt
index 3a0fcd4..ef27bc1 100644
--- a/mysql-test/suite/innodb/t/innodb-64k-master.opt
+++ b/mysql-test/suite/innodb/t/innodb-64k-master.opt
@@ -1 +1,3 @@
---default_storage_engine=InnoDB --innodb-buffer-pool-size=24M
+--default_storage_engine=InnoDB
+--innodb-buffer-pool-size=24M
+--innodb-log-file-size=32M
diff --git a/mysql-test/suite/innodb/t/innodb-64k.test b/mysql-test/suite/innodb/t/innodb-64k.test
index 0082953..bd0da6b 100644
--- a/mysql-test/suite/innodb/t/innodb-64k.test
+++ b/mysql-test/suite/innodb/t/innodb-64k.test
@@ -4,6 +4,9 @@
 --source include/have_innodb_64k.inc
 
 call mtr.add_suppression("InnoDB: Warning: innodb_page_size has been changed from default value *");
+call mtr.add_suppression("InnoDB: Resizing redo log from *");
+call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files.");
+call mtr.add_suppression("InnoDB: New log files created, LSN=*");
 
 --disable_query_log
 let $MYSQLD_DATADIR= `select @@datadir`;
@@ -264,33 +267,6 @@ c190 char(200), c191 char(200), c192 char(100),
 c81 char(157)
 ) ROW_FORMAT=dynamic;
 
-
-# Compressed table; 16063 bytes with 81 CHAR fields
-
---replace_regex /> [0-9]*/> max_row_size/
---error ER_TOO_BIG_ROWSIZE
-CREATE TABLE t1 (
-c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
-c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200),
-c11 char(200), c12 char(200), c13 char(200), c14 char(200), c15 char(200),
-c16 char(200), c17 char(200), c18 char(200), c19 char(200), c20 char(200),
-c21 char(200), c22 char(200), c23 char(200), c24 char(200), c25 char(200),
-c26 char(200), c27 char(200), c28 char(200), c29 char(200), c30 char(200),
-c31 char(200), c32 char(200), c33 char(200), c34 char(200), c35 char(200),
-c36 char(200), c37 char(200), c38 char(200), c39 char(200), c40 char(200),
-c41 char(200), c42 char(200), c43 char(200), c44 char(200), c45 char(200),
-c46 char(200), c47 char(200), c48 char(200), c49 char(200), c50 char(200),
-c51 char(200), c52 char(200), c53 char(200), c54 char(200), c55 char(200),
-c56 char(200), c57 char(200), c58 char(200), c59 char(200), c60 char(200),
-c61 char(200), c62 char(200), c63 char(200), c64 char(200), c65 char(200),
-c66 char(200), c67 char(200), c68 char(200), c69 char(200), c70 char(200),
-c71 char(200), c72 char(200), c73 char(200), c74 char(200), c75 char(200),
-c76 char(200), c77 char(200), c78 char(200), c79 char(200), c80 char(200),
-c81 char(62)
-) ROW_FORMAT=compressed;
-
-
-
 --echo # Test 8) Test creating a table that could lead to undo log overflow.
 
 CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob,
diff --git a/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test b/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test
index 8cbe493..79f7999 100644
--- a/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test
+++ b/mysql-test/suite/innodb/t/innodb-change-buffer-recovery.test
@@ -46,6 +46,9 @@ INSERT INTO t1 SELECT 0,b,c FROM t1;
 INSERT INTO t1 SELECT 0,b,c FROM t1;
 INSERT INTO t1 SELECT 0,b,c FROM t1;
 INSERT INTO t1 SELECT 0,b,c FROM t1;
+INSERT INTO t1 SELECT 0,b,c FROM t1;
+INSERT INTO t1 SELECT 0,b,c FROM t1;
+INSERT INTO t1 SELECT 0,b,c FROM t1;
 
 BEGIN;
 SELECT b FROM t1 LIMIT 3;
diff --git a/mysql-test/suite/innodb/t/innodb_blob_truncate.test b/mysql-test/suite/innodb/t/innodb_blob_truncate.test
new file mode 100644
index 0000000..8a4248c
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_blob_truncate.test
@@ -0,0 +1,45 @@
+--source include/have_innodb.inc
+--source include/have_innodb_16k.inc
+
+--disable_query_log
+let $innodb_file_format_orig = `SELECT @@innodb_file_format`;
+let $innodb_file_per_table_orig = `SELECT @@innodb_file_per_table`;
+--enable_query_log
+
+SET GLOBAL innodb_file_format = `Barracuda`;
+SET GLOBAL innodb_file_per_table = ON;
+
+create table t1(a blob) engine=innodb key_block_size=8;
+delimiter //;
+create function generate_blob()
+  returns varchar(20000)
+  begin
+    declare x varchar(20000) default '';
+    declare i int default 500;
+    while i > 0 do
+      set x = concat(sha1(i), x);
+      set i = i - 1;
+    end while;
+  return x;
+end //
+delimiter ;//
+insert into t1 select generate_blob();
+let $x = `select 20000 - length(a) from t1`;
+if ($x) {
+  echo Blob is truncated by $x bytes.;
+  die It must have been 20000 bytes.;
+}
+truncate t1;
+insert into t1 select generate_blob();
+let $x = `select 20000 - length(a) from t1`;
+if ($x) {
+  echo Blob is truncated by $x bytes.;
+  die It must have been 20000 bytes.;
+}
+drop table t1;
+drop function generate_blob;
+
+--disable_query_log
+EVAL SET GLOBAL innodb_file_per_table = $innodb_file_per_table_orig;
+EVAL SET GLOBAL innodb_file_format = $innodb_file_format_orig;
+--enable_query_log
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index f59c821..2e9c6b2 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -1339,7 +1339,7 @@ VARIABLE_NAME	INNODB_LOG_BUFFER_SIZE
 SESSION_VALUE	NULL
 GLOBAL_VALUE	1048576
 GLOBAL_VALUE_ORIGIN	CONFIG
-DEFAULT_VALUE	8388608
+DEFAULT_VALUE	16777216
 VARIABLE_SCOPE	GLOBAL
 VARIABLE_TYPE	BIGINT
 VARIABLE_COMMENT	The size of the buffer which InnoDB uses to write log to the log files on disk.
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 9588efc..6765290 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -2276,6 +2276,12 @@ btr_cur_optimistic_update(
 #endif /* UNIV_ZIP_DEBUG */
 
 	if (page_zip) {
+		if (page_zip_rec_needs_ext(new_rec_size, page_is_comp(page),
+					   dict_index_get_n_fields(index),
+					   page_zip_get_size(page_zip))) {
+			goto any_extern;
+		}
+
 		if (!btr_cur_update_alloc_zip(
 			    page_zip, page_cursor, index, *offsets,
 			    new_rec_size, true, mtr)) {
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index db30420..50ff4d7 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -745,9 +745,7 @@ fil_node_open_file(
 		}
 
 		if (!fsp_flags_is_compressed(flags)) {
-			node->size = (ulint)
-				(size_bytes
-				 / fsp_flags_get_page_size(flags));
+			node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
 		} else {
 			node->size = (ulint)
 				(size_bytes
@@ -4113,8 +4111,11 @@ fil_user_tablespace_find_space_id(
 					false, page, 0);
 			}
 
-			bool compressed_ok = !buf_page_is_corrupted(
-				false, page, page_size);
+			bool compressed_ok = false;
+			if (page_size <= UNIV_PAGE_SIZE_DEF) {
+				compressed_ok = !buf_page_is_corrupted(
+					false, page, page_size);
+			}
 
 			if (uncompressed_ok || compressed_ok) {
 
@@ -5846,6 +5847,8 @@ fil_io(
 		case 4096: zip_size_shift = 12; break;
 		case 8192: zip_size_shift = 13; break;
 		case 16384: zip_size_shift = 14; break;
+		case 32768: zip_size_shift = 15; break;
+		case 65536: zip_size_shift = 16; break;
 		default: ut_error;
 		}
 		offset = ((os_offset_t) block_offset << zip_size_shift)
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 078f9c9..454b2be 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -4772,7 +4772,10 @@ ha_innobase::max_supported_key_length() const
 
 	For page sizes = 16k, InnoDB historically reported 3500 bytes here,
 	But the MySQL limit of 3072 was always used through the handler
-	interface. */
+	interface.
+
+	Note: Handle 16k and 32k pages the same here since the limits
+	are higher than imposed by MySQL. */
 
 	switch (UNIV_PAGE_SIZE) {
 	case 4096:
@@ -10992,6 +10995,21 @@ create_options_are_invalid(
 		ret = "INDEX DIRECTORY";
 	}
 
+	if ((kbs_specified || row_format == ROW_TYPE_COMPRESSED)
+		&& UNIV_PAGE_SIZE > (1<<14)) {
+		push_warning(
+			thd, Sql_condition::WARN_LEVEL_WARN,
+			ER_ILLEGAL_HA_CREATE_OPTION,
+			"InnoDB: Cannot create a COMPRESSED table"
+			" when innodb_page_size > 16k.");
+
+		if (kbs_specified) {
+			ret = "KEY_BLOCK_SIZE";
+		} else {
+			ret = "ROW_TYPE";
+		}
+	}
+
 	return(ret);
 }
 
@@ -11349,6 +11367,17 @@ innobase_table_flags(
 		break;
 	}
 
+	/* Don't support compressed table when page size > 16k. */
+	if (zip_allowed && zip_ssize && UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) {
+		push_warning(
+			thd, Sql_condition::WARN_LEVEL_WARN,
+			ER_ILLEGAL_HA_CREATE_OPTION,
+			"InnoDB: Cannot create a COMPRESSED table"
+			" when innodb_page_size > 16k."
+			" Assuming ROW_FORMAT=COMPACT.");
+		zip_allowed = FALSE;
+	}
+
 	/* Set the table flags */
 	if (!zip_allowed) {
 		zip_ssize = 0;
@@ -18934,7 +18963,7 @@ static MYSQL_SYSVAR_ULONG(page_size, srv_page_size,
 static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
   PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
   "The size of the buffer which InnoDB uses to write log to the log files on disk.",
-  NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
+  NULL, NULL, 16*1024*1024L, 256*1024L, LONG_MAX, 1024);
 
 static MYSQL_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
   PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h
index a6797cd..4f2ca25 100644
--- a/storage/innobase/include/fsp0types.h
+++ b/storage/innobase/include/fsp0types.h
@@ -42,11 +42,21 @@ fseg_alloc_free_page) */
 #define	FSP_NO_DIR	((byte)113)	/*!< no order */
 /* @} */
 
+/** File space extent size in pages
+page size | file space extent size
+----------+-----------------------
+   4 KiB  | 256 pages = 1 MiB
+   8 KiB  | 128 pages = 1 MiB
+  16 KiB  |  64 pages = 1 MiB
+  32 KiB  |  64 pages = 2 MiB
+  64 KiB  |  64 pages = 4 MiB
+*/
 /** File space extent size (one megabyte if default two or four if not) in pages */
-#define	FSP_EXTENT_SIZE		((UNIV_PAGE_SIZE <= (1 << 14) ?		\
-				(1048576U / UNIV_PAGE_SIZE) : \
-				((UNIV_PAGE_SIZE <= 1 << 15) ? \
-				(2097152U / UNIV_PAGE_SIZE) : (4194304U / UNIV_PAGE_SIZE))))
+#define	FSP_EXTENT_SIZE		((UNIV_PAGE_SIZE <= (16384) ?	\
+				(1048576U / UNIV_PAGE_SIZE) :	\
+				((UNIV_PAGE_SIZE <= (32768)) ?	\
+				(2097152U / UNIV_PAGE_SIZE) :	\
+				(4194304U / UNIV_PAGE_SIZE))))
 
 /** File space extent size (four megabytes) in pages for MAX page size */
 #define	FSP_EXTENT_SIZE_MAX	(4194304U / UNIV_PAGE_SIZE_MAX)
diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h
index 94453cc..22899c2 100644
--- a/storage/innobase/include/rem0rec.h
+++ b/storage/innobase/include/rem0rec.h
@@ -982,7 +982,7 @@ are given in one byte (resp. two byte) format. */
 
 /* The data size of record must be smaller than this because we reserve
 two upmost bits in a two byte offset for special purposes */
-#define REC_MAX_DATA_SIZE	(16 * 1024)
+#define REC_MAX_DATA_SIZE	(16384)
 
 #ifdef WITH_WSREP
 int wsrep_rec_get_foreign_key(
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index a6804c7..a957b2c 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -372,10 +372,8 @@ Note: This must never change! */
 /** log2 of largest compressed page size (1<<14 == 16384 bytes).
 A compressed page directory entry reserves 14 bits for the start offset
 and 2 bits for flags. This limits the uncompressed page size to 16k.
-Even though a 16k uncompressed page can theoretically be compressed
-into a larger compressed page, it is not a useful feature so we will
-limit both with this same constant. */
-#define UNIV_ZIP_SIZE_SHIFT_MAX		15
+*/
+#define UNIV_ZIP_SIZE_SHIFT_MAX		14
 
 /* Define the Min, Max, Default page sizes. */
 /** Minimum Page Size Shift (power of 2) */
@@ -559,7 +557,7 @@ number indicate that a field contains a reference to an externally
 stored part of the field in the tablespace. The length field then
 contains the sum of the following flag and the locally stored len. */
 
-#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_MAX)
+#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_DEF)
 
 #if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER)
 #define HAVE_GCC_GT_2
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 94e3f64..0842971 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -672,8 +672,8 @@ page_zip_dir_encode(
 #if PAGE_ZIP_DIR_SLOT_MASK & (PAGE_ZIP_DIR_SLOT_MASK + 1)
 # error "PAGE_ZIP_DIR_SLOT_MASK is not 1 less than a power of 2"
 #endif
-#if PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_SIZE_DEF - 1
-# error "PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_SIZE_MAX - 1"
+#if PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_ZIP_SIZE_MAX - 1
+# error "PAGE_ZIP_DIR_SLOT_MASK < UNIV_ZIP_SIZE_MAX - 1"
 #endif
 		if (UNIV_UNLIKELY(rec_get_n_owned_new(rec))) {
 			offs |= PAGE_ZIP_DIR_SLOT_OWNED;
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index 2dba708..f970938 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -1479,7 +1479,7 @@ row_fts_merge_insert(
 		fd[i] = psort_info[i].merge_file[id]->fd;
 		foffs[i] = 0;
 
-		buf[i] = static_cast<unsigned char (*)[65536]>(
+		buf[i] = static_cast<mrec_buf_t*>(
 			mem_heap_alloc(heap, sizeof *buf[i]));
 
 		count_diag += (int) psort_info[i].merge_file[id]->n_rec;
diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc
index a8eeef4..1fc21f5 100644
--- a/storage/xtradb/btr/btr0cur.cc
+++ b/storage/xtradb/btr/btr0cur.cc
@@ -2417,6 +2417,12 @@ btr_cur_optimistic_update(
 #endif /* UNIV_ZIP_DEBUG */
 
 	if (page_zip) {
+		if (page_zip_rec_needs_ext(new_rec_size, page_is_comp(page),
+					   dict_index_get_n_fields(index),
+					   page_zip_get_size(page_zip))) {
+			goto any_extern;
+		}
+
 		if (!btr_cur_update_alloc_zip(
 			    page_zip, page_cursor, index, *offsets,
 			    new_rec_size, true, mtr, thr_get_trx(thr))) {
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 8823db1..6582771 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -747,9 +747,7 @@ fil_node_open_file(
 		}
 
 		if (!fsp_flags_is_compressed(flags)) {
-			node->size = (ulint)
-				(size_bytes
-				 / fsp_flags_get_page_size(flags));
+			node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
 		} else {
 			node->size = (ulint)
 				(size_bytes
@@ -4138,8 +4136,11 @@ fil_user_tablespace_find_space_id(
 					false, page, 0);
 			}
 
-			bool compressed_ok = !buf_page_is_corrupted(
-				false, page, page_size);
+			bool compressed_ok = false;
+			if (page_size <= UNIV_PAGE_SIZE_DEF) {
+				compressed_ok = !buf_page_is_corrupted(
+					false, page, page_size);
+			}
 
 			if (uncompressed_ok || compressed_ok) {
 
@@ -5876,6 +5877,8 @@ _fil_io(
 		case 4096: zip_size_shift = 12; break;
 		case 8192: zip_size_shift = 13; break;
 		case 16384: zip_size_shift = 14; break;
+		case 32768: zip_size_shift = 15; break;
+		case 65536: zip_size_shift = 16; break;
 		default: ut_error;
 		}
 		offset = ((os_offset_t) block_offset << zip_size_shift)
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 962b6e8..0a2a488 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -5261,7 +5261,10 @@ ha_innobase::max_supported_key_length() const
 
 	For page sizes = 16k, InnoDB historically reported 3500 bytes here,
 	But the MySQL limit of 3072 was always used through the handler
-	interface. */
+	interface.
+
+	Note: Handle 16k and 32k pages the same here since the limits
+	are higher than imposed by MySQL. */
 
 	switch (UNIV_PAGE_SIZE) {
 	case 4096:
@@ -11556,6 +11559,21 @@ create_options_are_invalid(
 		ret = "INDEX DIRECTORY";
 	}
 
+	if ((kbs_specified || row_format == ROW_TYPE_COMPRESSED)
+		&& UNIV_PAGE_SIZE > (1<<14)) {
+		push_warning(
+			thd, Sql_condition::WARN_LEVEL_WARN,
+			ER_ILLEGAL_HA_CREATE_OPTION,
+			"InnoDB: Cannot create a COMPRESSED table"
+			" when innodb_page_size > 16k.");
+
+		if (kbs_specified) {
+			ret = "KEY_BLOCK_SIZE";
+		} else {
+			ret = "ROW_TYPE";
+		}
+	}
+
 	return(ret);
 }
 
@@ -11910,6 +11928,17 @@ innobase_table_flags(
 		break;
 	}
 
+	/* Don't support compressed table when page size > 16k. */
+	if (zip_allowed && zip_ssize && UNIV_PAGE_SIZE > UNIV_PAGE_SIZE_DEF) {
+		push_warning(
+			thd, Sql_condition::WARN_LEVEL_WARN,
+			ER_ILLEGAL_HA_CREATE_OPTION,
+			"InnoDB: Cannot create a COMPRESSED table"
+			" when innodb_page_size > 16k."
+			" Assuming ROW_FORMAT=COMPACT.");
+		zip_allowed = FALSE;
+	}
+
 	/* Set the table flags */
 	if (!zip_allowed) {
 		zip_ssize = 0;
@@ -20094,7 +20123,7 @@ static MYSQL_SYSVAR_ULONG(page_size, srv_page_size,
 static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
   PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
   "The size of the buffer which InnoDB uses to write log to the log files on disk.",
-  NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
+  NULL, NULL, 16*1024*1024L, 256*1024L, LONG_MAX, 1024);
 
 static MYSQL_SYSVAR_LONGLONG(log_file_size, innobase_log_file_size,
   PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
diff --git a/storage/xtradb/include/fsp0types.h b/storage/xtradb/include/fsp0types.h
index c718140..509909d 100644
--- a/storage/xtradb/include/fsp0types.h
+++ b/storage/xtradb/include/fsp0types.h
@@ -41,11 +41,21 @@ fseg_alloc_free_page) */
 #define	FSP_NO_DIR	((byte)113)	/*!< no order */
 /* @} */
 
+/** File space extent size in pages
+page size | file space extent size
+----------+-----------------------
+   4 KiB  | 256 pages = 1 MiB
+   8 KiB  | 128 pages = 1 MiB
+  16 KiB  |  64 pages = 1 MiB
+  32 KiB  |  64 pages = 2 MiB
+  64 KiB  |  64 pages = 4 MiB
+*/
 /** File space extent size (one megabyte if default two or four if not) in pages */
-#define	FSP_EXTENT_SIZE		((UNIV_PAGE_SIZE <= (1 << 14) ?		\
-				(1048576U / UNIV_PAGE_SIZE) : \
-				((UNIV_PAGE_SIZE <= 1 << 15) ? \
-				(2097152U / UNIV_PAGE_SIZE) : (4194304U / UNIV_PAGE_SIZE))))
+#define	FSP_EXTENT_SIZE		((UNIV_PAGE_SIZE <= (16384) ?	\
+				(1048576U / UNIV_PAGE_SIZE) :	\
+				((UNIV_PAGE_SIZE <= (32768)) ?	\
+				(2097152U / UNIV_PAGE_SIZE) :	\
+				(4194304U / UNIV_PAGE_SIZE))))
 
 /** File space extent size (four megabytes) in pages for MAX page size */
 #define	FSP_EXTENT_SIZE_MAX	(4194304U / UNIV_PAGE_SIZE_MAX)
diff --git a/storage/xtradb/include/rem0rec.h b/storage/xtradb/include/rem0rec.h
index 238cb04..51c09bd 100644
--- a/storage/xtradb/include/rem0rec.h
+++ b/storage/xtradb/include/rem0rec.h
@@ -979,7 +979,7 @@ are given in one byte (resp. two byte) format. */
 
 /* The data size of record must be smaller than this because we reserve
 two upmost bits in a two byte offset for special purposes */
-#define REC_MAX_DATA_SIZE	(16 * 1024)
+#define REC_MAX_DATA_SIZE	(16384)
 
 #ifdef WITH_WSREP
 int wsrep_rec_get_foreign_key(
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 7b75c9f..81f8d0f 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -391,9 +391,7 @@ Note: This must never change! */
 /** log2 of largest compressed page size (1<<14 == 16384 bytes).
 A compressed page directory entry reserves 14 bits for the start offset
 and 2 bits for flags. This limits the uncompressed page size to 16k.
-Even though a 16k uncompressed page can theoretically be compressed
-into a larger compressed page, it is not a useful feature so we will
-limit both with this same constant. */
+*/
 #define UNIV_ZIP_SIZE_SHIFT_MAX		14
 
 /* Define the Min, Max, Default page sizes. */
@@ -580,7 +578,7 @@ number indicate that a field contains a reference to an externally
 stored part of the field in the tablespace. The length field then
 contains the sum of the following flag and the locally stored len. */
 
-#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_MAX)
+#define UNIV_EXTERN_STORAGE_FIELD (UNIV_SQL_NULL - UNIV_PAGE_SIZE_DEF)
 
 #if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER)
 #define HAVE_GCC_GT_2
diff --git a/storage/xtradb/page/page0zip.cc b/storage/xtradb/page/page0zip.cc
index 42ffd36..09da6ac 100644
--- a/storage/xtradb/page/page0zip.cc
+++ b/storage/xtradb/page/page0zip.cc
@@ -675,8 +675,8 @@ page_zip_dir_encode(
 #if PAGE_ZIP_DIR_SLOT_MASK & (PAGE_ZIP_DIR_SLOT_MASK + 1)
 # error "PAGE_ZIP_DIR_SLOT_MASK is not 1 less than a power of 2"
 #endif
-#if PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_SIZE_DEF - 1
-# error "PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_SIZE_MAX - 1"
+#if PAGE_ZIP_DIR_SLOT_MASK < UNIV_PAGE_ZIP_SIZE_MAX - 1
+# error "PAGE_ZIP_DIR_SLOT_MASK < UNIV_ZIP_SIZE_MAX - 1"
 #endif
 		if (UNIV_UNLIKELY(rec_get_n_owned_new(rec))) {
 			offs |= PAGE_ZIP_DIR_SLOT_OWNED;
diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc
index fad276c..55ac0a7 100644
--- a/storage/xtradb/row/row0ftsort.cc
+++ b/storage/xtradb/row/row0ftsort.cc
@@ -1482,7 +1482,7 @@ row_fts_merge_insert(
 		fd[i] = psort_info[i].merge_file[id]->fd;
 		foffs[i] = 0;
 
-		buf[i] = static_cast<unsigned char (*)[65536]>(
+		buf[i] = static_cast<mrec_buf_t*>(
 			mem_heap_alloc(heap, sizeof *buf[i]));
 
 		count_diag += (int) psort_info[i].merge_file[id]->n_rec;



More information about the commits mailing list