Description:
Creating a table with 100 varchar(200) columns in latin1 with ROW_FORMAT=DYNAMIC is rejected with
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.
This table is accepted by all MySQL versions before 8.0.46. The columns are variable-length, and
with ROW_FORMAT=DYNAMIC they can be stored fully off-page - the error message itself states that a
BLOB prefix of 0 bytes is stored inline. Rows holding short values therefore do fit in a page; only
rows where all 100 columns are at their maximum length cannot, and those should fail at INSERT time
with DB_TOO_BIG_RECORD rather than at CREATE time.
The regression comes from Bug#39129182, which made get_field_max_size() more accurate. That function
is also reused by the DDL page-fit check: for varchar(41-255) columns (1-byte length encoding, no
external-storage bit) the check now estimates the maximum declared length, so a wide but perfectly
usable table is refused.
Control experiment on the same instance: an identical table with 40 such columns (40 * 200 = 8000
bytes < 8126) is created successfully. This rules out an instance-level cause such as a special
innodb_strict_mode or page-size setting.
Affects: 26.10.0-trunk @ 561753af986 (verified 2026-10-26) and 26.7.0-debug @ 23e360a7fac.
How to repeat:
SET SESSION innodb_strict_mode = ON;
SET SESSION group_concat_max_len = 102400;
-- 100 columns x varchar(200) latin1
SET @cols = (SELECT GROUP_CONCAT(CONCAT('c', i, ' varchar(200)') ORDER BY i) FROM
(WITH RECURSIVE n(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM n WHERE i < 100) SELECT i FROM n) x);
SET @sql = CONCAT('CREATE TABLE bigrow (', @cols,
') ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET=latin1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
-- ACTUAL:
-- 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.
-- EXPECTED: the CREATE succeeds (as in every version before 8.0.46); a row whose values are
-- actually too long is rejected later at INSERT time with DB_TOO_BIG_RECORD.
-- Control: 40 columns (40 * 200 = 8000 bytes) is accepted, so the instance configuration is fine
SET SESSION group_concat_max_len = 102400;
SET @cols2 = (SELECT GROUP_CONCAT(CONCAT('c', i, ' varchar(200)') ORDER BY i) FROM
(WITH RECURSIVE n(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM n WHERE i < 40) SELECT i FROM n) x);
SET @sql2 = CONCAT('CREATE TABLE t40 (', @cols2,
') ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET=latin1');
PREPARE s2 FROM @sql2; EXECUTE s2; DEALLOCATE PREPARE s2; -- succeeds
Suggested fix:
Restore the previous behaviour, as done by Bug#39249507 / commit 99960bf74fa: let the CREATE
succeed, and raise DB_TOO_BIG_RECORD at INSERT time when the actual row does not fit. That is also
consistent with the record format, where a declared length <= 255 cannot flag external storage.
Description: Creating a table with 100 varchar(200) columns in latin1 with ROW_FORMAT=DYNAMIC is rejected with 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. This table is accepted by all MySQL versions before 8.0.46. The columns are variable-length, and with ROW_FORMAT=DYNAMIC they can be stored fully off-page - the error message itself states that a BLOB prefix of 0 bytes is stored inline. Rows holding short values therefore do fit in a page; only rows where all 100 columns are at their maximum length cannot, and those should fail at INSERT time with DB_TOO_BIG_RECORD rather than at CREATE time. The regression comes from Bug#39129182, which made get_field_max_size() more accurate. That function is also reused by the DDL page-fit check: for varchar(41-255) columns (1-byte length encoding, no external-storage bit) the check now estimates the maximum declared length, so a wide but perfectly usable table is refused. Control experiment on the same instance: an identical table with 40 such columns (40 * 200 = 8000 bytes < 8126) is created successfully. This rules out an instance-level cause such as a special innodb_strict_mode or page-size setting. Affects: 26.10.0-trunk @ 561753af986 (verified 2026-10-26) and 26.7.0-debug @ 23e360a7fac. How to repeat: SET SESSION innodb_strict_mode = ON; SET SESSION group_concat_max_len = 102400; -- 100 columns x varchar(200) latin1 SET @cols = (SELECT GROUP_CONCAT(CONCAT('c', i, ' varchar(200)') ORDER BY i) FROM (WITH RECURSIVE n(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM n WHERE i < 100) SELECT i FROM n) x); SET @sql = CONCAT('CREATE TABLE bigrow (', @cols, ') ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET=latin1'); PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s; -- ACTUAL: -- 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. -- EXPECTED: the CREATE succeeds (as in every version before 8.0.46); a row whose values are -- actually too long is rejected later at INSERT time with DB_TOO_BIG_RECORD. -- Control: 40 columns (40 * 200 = 8000 bytes) is accepted, so the instance configuration is fine SET SESSION group_concat_max_len = 102400; SET @cols2 = (SELECT GROUP_CONCAT(CONCAT('c', i, ' varchar(200)') ORDER BY i) FROM (WITH RECURSIVE n(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM n WHERE i < 40) SELECT i FROM n) x); SET @sql2 = CONCAT('CREATE TABLE t40 (', @cols2, ') ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET=latin1'); PREPARE s2 FROM @sql2; EXECUTE s2; DEALLOCATE PREPARE s2; -- succeeds Suggested fix: Restore the previous behaviour, as done by Bug#39249507 / commit 99960bf74fa: let the CREATE succeed, and raise DB_TOO_BIG_RECORD at INSERT time when the actual row does not fit. That is also consistent with the record format, where a declared length <= 255 cannot flag external storage.