Bug #115064 Row size too large is reported for insert operation with a large amount of data
Submitted: 20 May 2024 12:00 Modified: 3 Jun 2024 7:19
Reporter: Brian Yue (OCA) Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: DML Severity:S3 (Non-critical)
Version:8.0 OS:Any (rhel-7.4)
Assigned to: CPU Architecture:Any (x86-64)
Tags: INSERT ... SELECT, row size too large

[20 May 2024 12:00] Brian Yue
Description:
Hello,
  Recently we find a case that "row size too large" error is reported while executing "insert into select" operation, which is unexpected:
  1. the table is consist of 43 char(50) fields, and each field has the same value "AAAAAAAAAAAAAAAAAAAA" (20 characters), so each record has the same row size: 2150 bytes;
  2. after insert 4 records into the table, the first 6 times "insert into select" statements succeed, but later "insert into select" staments fail. Because each record has the same length, this behavior shows inconsistency.
  3. After increasing temptable_max_ram and tmp_table_size as bigger value, "insert into select" statements succeed again. But with bigger amount of data, "insert into select" statements will fail eventually.

How to repeat:
[yxxdb@localhost ~]$ mysql -uroot -p'db1x@NJ+1'  -S bin/mysql1.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.36 Source distribution

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
mysql>
mysql>
mysql> create database row_size;
Query OK, 1 row affected (0.00 sec)

mysql> use row_size
Database changed
mysql>
mysql> set global internal_tmp_mem_storage_engine = TempTable;
Query OK, 0 rows affected (0.00 sec)

mysql> set global temptable_max_ram = 2097152;
Query OK, 0 rows affected (0.00 sec)

mysql> set global tmp_table_size = 2097152;
Query OK, 0 rows affected (0.00 sec)

mysql> set global temptable_use_mmap = OFF;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table t1 (c1 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c2 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c3 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c4 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c5 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c6 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c7 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c8 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c9 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c10 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c11 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c12 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c13 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c14 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c15 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c16 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c17 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c18 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c19 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c20 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c21 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c22 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c23 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c24 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c25 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c26 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c27 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c28 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c29 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c30 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c31 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c32 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c33 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c34 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c35 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c36 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c37 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c38 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c39 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c40 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c41 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c42 char(50) default 'AAAAAAAAAAAAAAAAAAAA',c43 char(50) default 'AAAAAAAAAAAAAAAAAAAA') charset utf8mb4;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t1 () values ();
Query OK, 1 row affected (0.01 sec)

mysql> insert into t1 () values ();
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 () values ();
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 () values ();
Query OK, 1 row affected (0.00 sec)

mysql> insert into t1 select * from t1;
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
Query OK, 16 rows affected (0.00 sec)
Records: 16  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
Query OK, 32 rows affected (0.00 sec)
Records: 32  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
Query OK, 64 rows affected (0.01 sec)
Records: 64  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
Query OK, 128 rows affected (0.01 sec)
Records: 128  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
mysql> insert into t1 select * from t1;
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
mysql>
mysql>
mysql>
mysql>
mysql> set global tmp_table_size = 10485760;
Query OK, 0 rows affected (0.00 sec)

mysql> set global temptable_max_ram = 10485760;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 select * from t1;
Query OK, 256 rows affected (0.01 sec)
Records: 256  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
Query OK, 512 rows affected (0.01 sec)
Records: 512  Duplicates: 0  Warnings: 0

mysql> insert into t1 select * from t1;
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
mysql> insert into t1 select * from t1;
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.

Suggested fix:
Insert into a innodb table directly will succeed, but convert a memory table (temptable SE) into a innodb table fails at insert the same data, acctually success is expected.
[20 May 2024 13:38] MySQL Verification Team
Results of the test case with 24 (twenty four) inserts

Attachment: query_results.txt (text/plain), 4.39 KiB.

[20 May 2024 13:41] MySQL Verification Team
Hi Mr. Yue,

Thank you for your bug report.

However, this is not a bug.

You have simply run into the limit of your InnoDB's page size. This variable is configurable.

We changed that limit and had no problems running 24 inserts. We could have run 240 inserts and it would still work.

You will find our test case and its results attached in the "Files" tab, since the size is too large to fit into this comment.

Not a bug.
[3 Jun 2024 7:19] Brian Yue
Hello,
  I suppose to disagree with your appointment.

  In my testcase, the first 4 "insert into t1 select * from t1" statements succeed, but the later one fail with error "ERROR 1118 (42000): Row size too large (> 8126).".

  Firstly, this error means that the total size of a row to insert exceed the limit 8126, but actually it's not! Each row has 43 columns and each column has a value "'AAAAAAAAAAAAAAAAAAAA'", so the size of each row should be 43 * 20 bytes = 860 bytes, which is far from row size limit 8126 bytes.

  Secondly, we insert the exact the same row each time, no matter the first 4 insert operations or the later failed insert operation. Now that data never changes, why the first 4 inserts succeed and the later insert fails ? The behavior is not consistent. 

  No matter the table is converted from temptable to InnoDB or not, data to insert is never changed, and the size of data to insert is far from row size limit 8126. With regard to behavior changes after increase innodb_page_size to 64KB, some problem only exists in specific scenarios, not all.
[3 Jun 2024 10:01] MySQL Verification Team
Hi Mr. Yue,

Sorry, but we have thoroughly tested your report.

We have set innodb_page_size higher and your test completed without a single problem.

Not a bug.