commit d5c947a299d44ee6d2d1077c9332b34252830766 Author: poempeng Date: Tue Jun 2 12:41:03 2026 +0800 InnoDB: Relax max row size restriction for INSTANT DDL Problem ------- Since MySQL 8.0.29, InnoDB rejects INSTANT ADD/DROP COLUMN if the theoretical maximum row size (all columns at max length) exceeds the page record size limit. This is overly conservative: rows rarely reach their theoretical maximum in practice, and the restriction causes an upgrade regression for tables that previously allowed INSTANT DDL in early 8.0. Solution -------- Introduce a system variable `innodb_instant_ddl_strict_row_size` (default ON for backward compatibility): - ON: preserve the existing strict max-row-size check. - OFF: issue a warning and allow INSTANT DDL to proceed; the actual row size is enforced at DML time (INSERT/UPDATE). When the strict check is relaxed, a correctness issue arises during rollback: a record originally inserted at an older row version (with fewer columns) may be updated and then rolled back. If rollback rebuilds the record using current_row_version, all INSTANT-added columns are materialized with their default values, inflating the record beyond the page limit and causing rollback to fail. To fix this, the patch unconditionally records each row's original row_version in the undo log during UPDATE/DELETE. During rollback and MVCC version construction, the original row_version (instead of current_row_version) is used to rebuild the record, so only columns visible at the original version are stored — preserving the compact physical format and avoiding page-size overflow. For records inserted before any INSTANT DDL (no version flag in the record header), version 0 is written to the undo log, representing the original table schema. During rollback, these records are restored with the versioned bit set and version=0, maintaining their original column set. diff --git a/mysql-test/suite/innodb/r/instant_ddl_rollback_max_row_size.result b/mysql-test/suite/innodb/r/instant_ddl_rollback_max_row_size.result new file mode 100644 index 00000000000..a2d9169cb88 --- /dev/null +++ b/mysql-test/suite/innodb/r/instant_ddl_rollback_max_row_size.result @@ -0,0 +1,138 @@ +SET GLOBAL innodb_instant_ddl_strict_row_size = OFF; +################################################################ +# Scenario 1: Rollback from version 1 to version 0 +# Record inserted before any INSTANT DDL (no version flag), +# then INSTANT ADD many columns creating version 1. +# UPDATE + ROLLBACK must restore to version 0. +################################################################ +CREATE TABLE t1 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; +# First INSTANT ADD with COPY to establish baseline schema +alter table t1 add column c1 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=copy; +# Insert a row at version 0 (before any INSTANT DDL) +insert into t1 values(repeat('b',100), repeat('a',100)); +# INSTANT ADD many CHAR(200) columns → version 1, exceeding row size limit +alter table t1 add column c2 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c3 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c4 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c5 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c6 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c7 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c8 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c9 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c10 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c11 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c12 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c13 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c14 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c15 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c16 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c17 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c18 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c19 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c20 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c21 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c22 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c23 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c24 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c25 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c26 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c27 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c28 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c29 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c30 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c31 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c32 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c33 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c34 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c35 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c36 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c37 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c38 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c39 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c40 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c41 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c42 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=instant; +Warnings: +Warning 4157 InnoDB: INSTANT DDL on table test/t1: max row size (8306) may exceed page limit (8126) after adding 41 column(s). Proceeding because innodb_instant_ddl_strict_row_size=OFF. +Warning 4157 InnoDB: INSTANT DDL on table test/t1: max row size (8306) may exceed page limit (8126) after adding 41 column(s). Proceeding because innodb_instant_ddl_strict_row_size=OFF. +Warning 139 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. +# UPDATE the row (sets all INSTANT columns to NULL, shrinking the record) +begin; +update t1 set c0='cccs', c1=NULL, c2=NULL, c3=NULL, c4=NULL, c5=NULL, c6=NULL, c7=NULL, c8=NULL, c9=NULL, c10=NULL, c11=NULL, c12=NULL, c13=NULL, c14=NULL, c15=NULL, c16=NULL, c17=NULL, c18=NULL, c19=NULL, c20=NULL, c21=NULL, c22=NULL, c23=NULL, c24=NULL, c25=NULL, c26=NULL, c27=NULL, c28=NULL, c29=NULL, c30=NULL, c31=NULL, c32=NULL, c33=NULL, c34=NULL, c35=NULL, c36=NULL, c37=NULL, c38=NULL, c39=NULL, c40=NULL, c41=NULL, c42=NULL; +# Rollback should succeed without crash (restores to version 0) +rollback; +# Verify table data is intact after rollback +select c0, left(c1, 10), left(c2, 10) from t1; +c0 left(c1, 10) left(c2, 10) +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb aaaaaaaaaa aaaaaaaaaa +DROP TABLE t1; +################################################################ +# Scenario 2: Rollback from version 2 to version 1 +# Record inserted after first INSTANT ADD (version 1), +# then second INSTANT ADD creates version 2. +# UPDATE + ROLLBACK must restore to version 1. +################################################################ +CREATE TABLE t2 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; +# First INSTANT ADD → version 1 +alter table t2 add column c1 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=instant; +# Insert a row at version 1 +insert into t2 values(repeat('b',100), repeat('a',100)); +# Second INSTANT ADD: many columns → version 2, exceeding row size limit +alter table t2 add column c2 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c3 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c4 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c5 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c6 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c7 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c8 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c9 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c10 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c11 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c12 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c13 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c14 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c15 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c16 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c17 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c18 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c19 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c20 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c21 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c22 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c23 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c24 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c25 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c26 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c27 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c28 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c29 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c30 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c31 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c32 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c33 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c34 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c35 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c36 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c37 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c38 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c39 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c40 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c41 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c42 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=instant; +Warnings: +Warning 4157 InnoDB: INSTANT DDL on table test/t2: max row size (8307) may exceed page limit (8126) after adding 41 column(s). Proceeding because innodb_instant_ddl_strict_row_size=OFF. +Warning 4157 InnoDB: INSTANT DDL on table test/t2: max row size (8307) may exceed page limit (8126) after adding 41 column(s). Proceeding because innodb_instant_ddl_strict_row_size=OFF. +Warning 139 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. +# UPDATE the row +begin; +update t2 set c0='cccs', c1=NULL, c2=NULL, c3=NULL, c4=NULL, c5=NULL, c6=NULL, c7=NULL, c8=NULL, c9=NULL, c10=NULL, c11=NULL, c12=NULL, c13=NULL, c14=NULL, c15=NULL, c16=NULL, c17=NULL, c18=NULL, c19=NULL, c20=NULL, c21=NULL, c22=NULL, c23=NULL, c24=NULL, c25=NULL, c26=NULL, c27=NULL, c28=NULL, c29=NULL, c30=NULL, c31=NULL, c32=NULL, c33=NULL, c34=NULL, c35=NULL, c36=NULL, c37=NULL, c38=NULL, c39=NULL, c40=NULL, c41=NULL, c42=NULL; +# Rollback should succeed (restores to version 1) +rollback; +# Verify table data is intact after rollback +select c0, left(c1, 10), left(c2, 10) from t2; +c0 left(c1, 10) left(c2, 10) +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb aaaaaaaaaa aaaaaaaaaa +DROP TABLE t2; +################################################################ +# Scenario 3: Multiple rows at different versions +# Row r0 inserted at version 0, row r1 inserted at version 1, +# then INSTANT ADD creates version 2. +# UPDATE all rows + ROLLBACK must restore each to its version. +################################################################ +CREATE TABLE t3 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; +# Insert row r0 at version 0 (no INSTANT DDL yet) +insert into t3 values(repeat('x',50)); +# First INSTANT ADD → version 1 +alter table t3 add column c1 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=instant; +# Insert row r1 at version 1 +insert into t3 values(repeat('y',50), repeat('z',50)); +# Second INSTANT ADD: many columns → version 2 +alter table t3 add column c2 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c3 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c4 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c5 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c6 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c7 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c8 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c9 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c10 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c11 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c12 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c13 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c14 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c15 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c16 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c17 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c18 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c19 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c20 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c21 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c22 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c23 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c24 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c25 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c26 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c27 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c28 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c29 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c30 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c31 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c32 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c33 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c34 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c35 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c36 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c37 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c38 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c39 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c40 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c41 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=instant; +Warnings: +Warning 4157 InnoDB: INSTANT DDL on table test/t3: max row size (8307) may exceed page limit (8126) after adding 40 column(s). Proceeding because innodb_instant_ddl_strict_row_size=OFF. +Warning 4157 InnoDB: INSTANT DDL on table test/t3: max row size (8307) may exceed page limit (8126) after adding 40 column(s). Proceeding because innodb_instant_ddl_strict_row_size=OFF. +Warning 139 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. +# UPDATE both rows +begin; +update t3 set c0='updated', c1=NULL; +# Rollback should restore r0 to version 0, r1 to version 1 +rollback; +# Verify both rows are intact +select c0, left(c1, 10) from t3 order by c0; +c0 left(c1, 10) +xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx aaaaaaaaaa +yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy zzzzzzzzzz +DROP TABLE t3; +################################################################ +# Scenario 4: INSERT + ROLLBACK on table with relaxed row size +# Insert a new row into a table where INSTANT ADD has pushed +# max row size over the limit, then rollback the insert. +# The undo-insert (delete) must handle the versioned record. +################################################################ +CREATE TABLE t4 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; +# INSTANT ADD many columns → version 1 +alter table t4 add column c1 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c2 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c3 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c4 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c5 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c6 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c7 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c8 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c9 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c10 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c11 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c12 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c13 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c14 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c15 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c16 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c17 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c18 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c19 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c20 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c21 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c22 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c23 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c24 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c25 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c26 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c27 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c28 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c29 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c30 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c31 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c32 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c33 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c34 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c35 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c36 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c37 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c38 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c39 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c40 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=instant; +# INSERT a row and then rollback +begin; +insert into t4(c0) values(repeat('d',100)); +# Rollback should delete the inserted row without crash +rollback; +# Verify table is empty +select count(*) from t4; +count(*) +0 +DROP TABLE t4; +################################################################ +# Scenario 5: DELETE + ROLLBACK +# A row inserted at version 0 is deleted after INSTANT ADD +# (version 1). Rollback must re-insert the row at version 0. +################################################################ +CREATE TABLE t5 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; +# Insert a row at version 0 +insert into t5 values(repeat('e',100)); +# INSTANT ADD many columns → version 1 +alter table t5 add column c1 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c2 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c3 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c4 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c5 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c6 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c7 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c8 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c9 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c10 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c11 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c12 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c13 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c14 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c15 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c16 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c17 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c18 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c19 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c20 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c21 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c22 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c23 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c24 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c25 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c26 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c27 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c28 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c29 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c30 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c31 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c32 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c33 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c34 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c35 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c36 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c37 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c38 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c39 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', add column c40 char(200) default 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', algorithm=instant; +# DELETE the row and then rollback +begin; +delete from t5; +# Rollback should re-insert the row at version 0 without crash +rollback; +# Verify the row is restored +select left(c0, 10), c1 from t5; +left(c0, 10) c1 +eeeeeeeeee aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +DROP TABLE t5; +########### +# CLEANUP # +########### +SET GLOBAL innodb_instant_ddl_strict_row_size = ON; diff --git a/mysql-test/suite/innodb/t/instant_ddl_rollback_max_row_size.test b/mysql-test/suite/innodb/t/instant_ddl_rollback_max_row_size.test new file mode 100644 index 00000000000..3ac84b211a7 --- /dev/null +++ b/mysql-test/suite/innodb/t/instant_ddl_rollback_max_row_size.test @@ -0,0 +1,185 @@ +########################################################################## +# Test INSTANT DDL rollback when row size exceeds the page limit. +# +# When a table has many INSTANT ADD columns with large CHAR defaults, +# the total row size may exceed the page limit. This test verifies that +# UPDATE + ROLLBACK on such a table works correctly without crash. +# +# The fix ensures that undo records correctly encode the row_version +# (version 0 for records inserted before INSTANT DDL), so rollback +# restores records to their original physical format with versioned bit +# + version=0, allowing the record to be interpreted using only the +# columns from the original table definition. +# +# Scenarios tested: +# 1. Rollback from version 1 to version 0 (record inserted at v0, +# INSTANT ADD creates v1, UPDATE + ROLLBACK) +# 2. Rollback from version 2 to version 1 (record inserted at v1, +# second INSTANT ADD creates v2, UPDATE + ROLLBACK) +# 3. Multiple rows at different versions, UPDATE all + ROLLBACK +# 4. INSERT + ROLLBACK on a table with relaxed row size +# 5. DELETE + ROLLBACK (undo insert restores row at original version) +########################################################################## + +# Use a helper variable for the long default value +let $def200=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + +SET GLOBAL innodb_instant_ddl_strict_row_size = OFF; + +--echo ################################################################ +--echo # Scenario 1: Rollback from version 1 to version 0 +--echo # Record inserted before any INSTANT DDL (no version flag), +--echo # then INSTANT ADD many columns creating version 1. +--echo # UPDATE + ROLLBACK must restore to version 0. +--echo ################################################################ + +CREATE TABLE t1 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; + +--echo # First INSTANT ADD with COPY to establish baseline schema +eval alter table t1 add column c1 char(200) default '$def200', algorithm=copy; + +--echo # Insert a row at version 0 (before any INSTANT DDL) +insert into t1 values(repeat('b',100), repeat('a',100)); + +--echo # INSTANT ADD many CHAR(200) columns → version 1, exceeding row size limit +eval alter table t1 add column c2 char(200) default '$def200', add column c3 char(200) default '$def200', add column c4 char(200) default '$def200', add column c5 char(200) default '$def200', add column c6 char(200) default '$def200', add column c7 char(200) default '$def200', add column c8 char(200) default '$def200', add column c9 char(200) default '$def200', add column c10 char(200) default '$def200', add column c11 char(200) default '$def200', add column c12 char(200) default '$def200', add column c13 char(200) default '$def200', add column c14 char(200) default '$def200', add column c15 char(200) default '$def200', add column c16 char(200) default '$def200', add column c17 char(200) default '$def200', add column c18 char(200) default '$def200', add column c19 char(200) default '$def200', add column c20 char(200) default '$def200', add column c21 char(200) default '$def200', add column c22 char(200) default '$def200', add column c23 char(200) default '$def200', add column c24 char(200) default '$def200', add column c25 char(200) default '$def200', add column c26 char(200) default '$def200', add column c27 char(200) default '$def200', add column c28 char(200) default '$def200', add column c29 char(200) default '$def200', add column c30 char(200) default '$def200', add column c31 char(200) default '$def200', add column c32 char(200) default '$def200', add column c33 char(200) default '$def200', add column c34 char(200) default '$def200', add column c35 char(200) default '$def200', add column c36 char(200) default '$def200', add column c37 char(200) default '$def200', add column c38 char(200) default '$def200', add column c39 char(200) default '$def200', add column c40 char(200) default '$def200', add column c41 char(200) default '$def200', add column c42 char(200) default '$def200', algorithm=instant; + +--echo # UPDATE the row (sets all INSTANT columns to NULL, shrinking the record) +begin; +update t1 set c0='cccs', c1=NULL, c2=NULL, c3=NULL, c4=NULL, c5=NULL, c6=NULL, c7=NULL, c8=NULL, c9=NULL, c10=NULL, c11=NULL, c12=NULL, c13=NULL, c14=NULL, c15=NULL, c16=NULL, c17=NULL, c18=NULL, c19=NULL, c20=NULL, c21=NULL, c22=NULL, c23=NULL, c24=NULL, c25=NULL, c26=NULL, c27=NULL, c28=NULL, c29=NULL, c30=NULL, c31=NULL, c32=NULL, c33=NULL, c34=NULL, c35=NULL, c36=NULL, c37=NULL, c38=NULL, c39=NULL, c40=NULL, c41=NULL, c42=NULL; + +--echo # Rollback should succeed without crash (restores to version 0) +rollback; + +--echo # Verify table data is intact after rollback +select c0, left(c1, 10), left(c2, 10) from t1; + +DROP TABLE t1; + +--echo ################################################################ +--echo # Scenario 2: Rollback from version 2 to version 1 +--echo # Record inserted after first INSTANT ADD (version 1), +--echo # then second INSTANT ADD creates version 2. +--echo # UPDATE + ROLLBACK must restore to version 1. +--echo ################################################################ + +CREATE TABLE t2 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; + +--echo # First INSTANT ADD → version 1 +eval alter table t2 add column c1 char(200) default '$def200', algorithm=instant; + +--echo # Insert a row at version 1 +insert into t2 values(repeat('b',100), repeat('a',100)); + +--echo # Second INSTANT ADD: many columns → version 2, exceeding row size limit +eval alter table t2 add column c2 char(200) default '$def200', add column c3 char(200) default '$def200', add column c4 char(200) default '$def200', add column c5 char(200) default '$def200', add column c6 char(200) default '$def200', add column c7 char(200) default '$def200', add column c8 char(200) default '$def200', add column c9 char(200) default '$def200', add column c10 char(200) default '$def200', add column c11 char(200) default '$def200', add column c12 char(200) default '$def200', add column c13 char(200) default '$def200', add column c14 char(200) default '$def200', add column c15 char(200) default '$def200', add column c16 char(200) default '$def200', add column c17 char(200) default '$def200', add column c18 char(200) default '$def200', add column c19 char(200) default '$def200', add column c20 char(200) default '$def200', add column c21 char(200) default '$def200', add column c22 char(200) default '$def200', add column c23 char(200) default '$def200', add column c24 char(200) default '$def200', add column c25 char(200) default '$def200', add column c26 char(200) default '$def200', add column c27 char(200) default '$def200', add column c28 char(200) default '$def200', add column c29 char(200) default '$def200', add column c30 char(200) default '$def200', add column c31 char(200) default '$def200', add column c32 char(200) default '$def200', add column c33 char(200) default '$def200', add column c34 char(200) default '$def200', add column c35 char(200) default '$def200', add column c36 char(200) default '$def200', add column c37 char(200) default '$def200', add column c38 char(200) default '$def200', add column c39 char(200) default '$def200', add column c40 char(200) default '$def200', add column c41 char(200) default '$def200', add column c42 char(200) default '$def200', algorithm=instant; + +--echo # UPDATE the row +begin; +update t2 set c0='cccs', c1=NULL, c2=NULL, c3=NULL, c4=NULL, c5=NULL, c6=NULL, c7=NULL, c8=NULL, c9=NULL, c10=NULL, c11=NULL, c12=NULL, c13=NULL, c14=NULL, c15=NULL, c16=NULL, c17=NULL, c18=NULL, c19=NULL, c20=NULL, c21=NULL, c22=NULL, c23=NULL, c24=NULL, c25=NULL, c26=NULL, c27=NULL, c28=NULL, c29=NULL, c30=NULL, c31=NULL, c32=NULL, c33=NULL, c34=NULL, c35=NULL, c36=NULL, c37=NULL, c38=NULL, c39=NULL, c40=NULL, c41=NULL, c42=NULL; + +--echo # Rollback should succeed (restores to version 1) +rollback; + +--echo # Verify table data is intact after rollback +select c0, left(c1, 10), left(c2, 10) from t2; + +DROP TABLE t2; + +--echo ################################################################ +--echo # Scenario 3: Multiple rows at different versions +--echo # Row r0 inserted at version 0, row r1 inserted at version 1, +--echo # then INSTANT ADD creates version 2. +--echo # UPDATE all rows + ROLLBACK must restore each to its version. +--echo ################################################################ + +CREATE TABLE t3 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; + +--echo # Insert row r0 at version 0 (no INSTANT DDL yet) +insert into t3 values(repeat('x',50)); + +--echo # First INSTANT ADD → version 1 +eval alter table t3 add column c1 char(200) default '$def200', algorithm=instant; + +--echo # Insert row r1 at version 1 +insert into t3 values(repeat('y',50), repeat('z',50)); + +--echo # Second INSTANT ADD: many columns → version 2 +eval alter table t3 add column c2 char(200) default '$def200', add column c3 char(200) default '$def200', add column c4 char(200) default '$def200', add column c5 char(200) default '$def200', add column c6 char(200) default '$def200', add column c7 char(200) default '$def200', add column c8 char(200) default '$def200', add column c9 char(200) default '$def200', add column c10 char(200) default '$def200', add column c11 char(200) default '$def200', add column c12 char(200) default '$def200', add column c13 char(200) default '$def200', add column c14 char(200) default '$def200', add column c15 char(200) default '$def200', add column c16 char(200) default '$def200', add column c17 char(200) default '$def200', add column c18 char(200) default '$def200', add column c19 char(200) default '$def200', add column c20 char(200) default '$def200', add column c21 char(200) default '$def200', add column c22 char(200) default '$def200', add column c23 char(200) default '$def200', add column c24 char(200) default '$def200', add column c25 char(200) default '$def200', add column c26 char(200) default '$def200', add column c27 char(200) default '$def200', add column c28 char(200) default '$def200', add column c29 char(200) default '$def200', add column c30 char(200) default '$def200', add column c31 char(200) default '$def200', add column c32 char(200) default '$def200', add column c33 char(200) default '$def200', add column c34 char(200) default '$def200', add column c35 char(200) default '$def200', add column c36 char(200) default '$def200', add column c37 char(200) default '$def200', add column c38 char(200) default '$def200', add column c39 char(200) default '$def200', add column c40 char(200) default '$def200', add column c41 char(200) default '$def200', algorithm=instant; + +--echo # UPDATE both rows +begin; +update t3 set c0='updated', c1=NULL; + +--echo # Rollback should restore r0 to version 0, r1 to version 1 +rollback; + +--echo # Verify both rows are intact +select c0, left(c1, 10) from t3 order by c0; + +DROP TABLE t3; + +--echo ################################################################ +--echo # Scenario 4: INSERT + ROLLBACK on table with relaxed row size +--echo # Insert a new row into a table where INSTANT ADD has pushed +--echo # max row size over the limit, then rollback the insert. +--echo # The undo-insert (delete) must handle the versioned record. +--echo ################################################################ + +CREATE TABLE t4 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; + +--echo # INSTANT ADD many columns → version 1 +eval alter table t4 add column c1 char(200) default '$def200', add column c2 char(200) default '$def200', add column c3 char(200) default '$def200', add column c4 char(200) default '$def200', add column c5 char(200) default '$def200', add column c6 char(200) default '$def200', add column c7 char(200) default '$def200', add column c8 char(200) default '$def200', add column c9 char(200) default '$def200', add column c10 char(200) default '$def200', add column c11 char(200) default '$def200', add column c12 char(200) default '$def200', add column c13 char(200) default '$def200', add column c14 char(200) default '$def200', add column c15 char(200) default '$def200', add column c16 char(200) default '$def200', add column c17 char(200) default '$def200', add column c18 char(200) default '$def200', add column c19 char(200) default '$def200', add column c20 char(200) default '$def200', add column c21 char(200) default '$def200', add column c22 char(200) default '$def200', add column c23 char(200) default '$def200', add column c24 char(200) default '$def200', add column c25 char(200) default '$def200', add column c26 char(200) default '$def200', add column c27 char(200) default '$def200', add column c28 char(200) default '$def200', add column c29 char(200) default '$def200', add column c30 char(200) default '$def200', add column c31 char(200) default '$def200', add column c32 char(200) default '$def200', add column c33 char(200) default '$def200', add column c34 char(200) default '$def200', add column c35 char(200) default '$def200', add column c36 char(200) default '$def200', add column c37 char(200) default '$def200', add column c38 char(200) default '$def200', add column c39 char(200) default '$def200', add column c40 char(200) default '$def200', algorithm=instant; + +--echo # INSERT a row and then rollback +begin; +insert into t4(c0) values(repeat('d',100)); + +--echo # Rollback should delete the inserted row without crash +rollback; + +--echo # Verify table is empty +select count(*) from t4; + +DROP TABLE t4; + +--echo ################################################################ +--echo # Scenario 5: DELETE + ROLLBACK +--echo # A row inserted at version 0 is deleted after INSTANT ADD +--echo # (version 1). Rollback must re-insert the row at version 0. +--echo ################################################################ + +CREATE TABLE t5 ( +c0 text +) charset latin1 ROW_FORMAT=dynamic; + +--echo # Insert a row at version 0 +insert into t5 values(repeat('e',100)); + +--echo # INSTANT ADD many columns → version 1 +eval alter table t5 add column c1 char(200) default '$def200', add column c2 char(200) default '$def200', add column c3 char(200) default '$def200', add column c4 char(200) default '$def200', add column c5 char(200) default '$def200', add column c6 char(200) default '$def200', add column c7 char(200) default '$def200', add column c8 char(200) default '$def200', add column c9 char(200) default '$def200', add column c10 char(200) default '$def200', add column c11 char(200) default '$def200', add column c12 char(200) default '$def200', add column c13 char(200) default '$def200', add column c14 char(200) default '$def200', add column c15 char(200) default '$def200', add column c16 char(200) default '$def200', add column c17 char(200) default '$def200', add column c18 char(200) default '$def200', add column c19 char(200) default '$def200', add column c20 char(200) default '$def200', add column c21 char(200) default '$def200', add column c22 char(200) default '$def200', add column c23 char(200) default '$def200', add column c24 char(200) default '$def200', add column c25 char(200) default '$def200', add column c26 char(200) default '$def200', add column c27 char(200) default '$def200', add column c28 char(200) default '$def200', add column c29 char(200) default '$def200', add column c30 char(200) default '$def200', add column c31 char(200) default '$def200', add column c32 char(200) default '$def200', add column c33 char(200) default '$def200', add column c34 char(200) default '$def200', add column c35 char(200) default '$def200', add column c36 char(200) default '$def200', add column c37 char(200) default '$def200', add column c38 char(200) default '$def200', add column c39 char(200) default '$def200', add column c40 char(200) default '$def200', algorithm=instant; + +--echo # DELETE the row and then rollback +begin; +delete from t5; + +--echo # Rollback should re-insert the row at version 0 without crash +rollback; + +--echo # Verify the row is restored +select left(c0, 10), c1 from t5; + +DROP TABLE t5; + +--echo ########### +--echo # CLEANUP # +--echo ########### +SET GLOBAL innodb_instant_ddl_strict_row_size = ON; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index 5c1d41be120..3940a9711fc 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -3446,7 +3446,11 @@ bool materialize_instant_default(const dict_index_t *index, const rec_t *rec) { if (rec_new_is_versioned(rec)) { uint8_t v = rec_get_instant_row_version_new(rec); if (v == 0) { - ut_ad(index->has_instant_cols()); + /* version 0 can appear in two cases: + 1. Upgraded table with old-style INSTANT ADD (has_instant_cols) + 2. Rollback restoring a pre-INSTANT-DDL row to version 0 + in a table that has new-style row versions (has_row_versions) */ + ut_ad(index->has_instant_cols() || index->has_row_versions()); } else { ut_ad(index->has_row_versions()); } @@ -3596,6 +3600,17 @@ dberr_t btr_cur_optimistic_update(ulint flags, btr_cur_t *cursor, row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, false, *heap); + /* When restoring a previous row version (e.g., during rollback), use + the original row_version from the undo record so that the physical record + is restored to its original format with only the columns visible in that + version. For records inserted before any INSTANT DDL, old_row_version + is 0, restoring them with versioned bit + version=0 so they are + interpreted using only the original table columns. */ + if ((flags & BTR_NO_UNDO_LOG_FLAG) && index->has_row_versions() && + update->old_row_version != INVALID_ROW_VERSION) { + new_entry->row_version = update->old_row_version; + } + if (!materialize_instant_default(index, rec)) { new_entry->ignore_trailing_default(index); } @@ -3869,6 +3884,17 @@ dberr_t btr_cur_pessimistic_update(ulint flags, btr_cur_t *cursor, row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update, false, entry_heap); + /* When restoring a previous row version (e.g., during rollback), use + the original row_version from the undo record so that the physical record + is restored to its original format with only the columns visible in that + version. For records inserted before any INSTANT DDL, old_row_version + is 0, restoring them with versioned bit + version=0 so they are + interpreted using only the original table columns. */ + if ((flags & BTR_NO_UNDO_LOG_FLAG) && index->has_row_versions() && + update->old_row_version != INVALID_ROW_VERSION) { + new_entry->row_version = update->old_row_version; + } + if (!materialize_instant_default(index, rec)) { new_entry->ignore_trailing_default(index); } diff --git a/storage/innobase/dict/dict0inst.cc b/storage/innobase/dict/dict0inst.cc index f97dfe9588a..8b99b67e70a 100644 --- a/storage/innobase/dict/dict0inst.cc +++ b/storage/innobase/dict/dict0inst.cc @@ -30,9 +30,13 @@ Instant DDL interface implementation Created 2020-04-24 by Mayank Prasad */ #include "dict0inst.h" +#include +#include +#include #include "dict0dd.h" #include "dict0dict.h" #include "ha_innodb.h" +#include "srv0srv.h" static void populate_to_be_instant_columns_low( const Alter_inplace_info *ha_alter_info, const TABLE *old_table, @@ -65,11 +69,24 @@ bool Instant_ddl_impl::is_instant_add_drop_possible( dict_table, index, page_rec_max, page_ptr_max, current_max_size); if (res) { - /* Table is already in a state where possible row size can go beyond - permissible size limit. Don't allow INSTANT ADD */ - ib::error(ER_IB_INSTANT_ADD_DROP_COLUMN_NOT_ALLOWED, - dict_table->name.m_name, current_max_size, page_rec_max); - return false; + if (!srv_instant_ddl_strict_row_size) { + /* Strict mode is OFF: warn but allow INSTANT DDL to proceed. + No need to check new columns since the table already exceeds limit. */ + push_warning_printf( + current_thd, Sql_condition::SL_WARNING, + ER_INNODB_INSTANT_ADD_DROP_NOT_SUPPORTED_MAX_SIZE, + "InnoDB: INSTANT DDL on table %s: current max row size (%zu)" + " exceeds page limit (%zu). Proceeding because" + " innodb_instant_ddl_strict_row_size=OFF.", + dict_table->name.m_name, current_max_size, page_rec_max); + return true; + } else { + /* Table is already in a state where possible row size can go beyond + permissible size limit. Don't allow INSTANT ADD */ + ib::error(ER_IB_INSTANT_ADD_DROP_COLUMN_NOT_ALLOWED, + dict_table->name.m_name, current_max_size, page_rec_max); + return false; + } } for (auto field : cols_to_add) { @@ -101,10 +118,24 @@ bool Instant_ddl_impl
::is_instant_add_drop_possible( current_max_size += field_max_size; if (current_max_size > page_rec_max) { - /* Don't allow INSTANT ADD */ - ib::error(ER_IB_INSTANT_ADD_NOT_POSSIBLE, cols_to_add.size(), - dict_table->name.m_name, current_max_size, page_rec_max); - return false; + if (!srv_instant_ddl_strict_row_size) { + /* Strict mode is OFF: warn but allow INSTANT DDL to proceed */ + push_warning_printf( + current_thd, Sql_condition::SL_WARNING, + ER_INNODB_INSTANT_ADD_DROP_NOT_SUPPORTED_MAX_SIZE, + "InnoDB: INSTANT DDL on table %s: max row size (%zu) may" + " exceed page limit (%zu) after adding %zu column(s)." + " Proceeding because innodb_instant_ddl_strict_row_size=OFF.", + dict_table->name.m_name, current_max_size, page_rec_max, + cols_to_add.size()); + /* Already warned, no need to check remaining columns */ + break; + } else { + /* Don't allow INSTANT ADD */ + ib::error(ER_IB_INSTANT_ADD_NOT_POSSIBLE, cols_to_add.size(), + dict_table->name.m_name, current_max_size, page_rec_max); + return false; + } } } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a3aa979959f..38b5328a20d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -22241,6 +22241,13 @@ static MYSQL_SYSVAR_BOOL( "Include delete marked records when calculating persistent statistics", nullptr, nullptr, false); +static MYSQL_SYSVAR_BOOL( + instant_ddl_strict_row_size, srv_instant_ddl_strict_row_size, + PLUGIN_VAR_OPCMDARG, + "When ON (default), reject INSTANT DDL if the resulting row size may " + "exceed the page limit. When OFF, only issue a warning and proceed.", + nullptr, nullptr, true); + static MYSQL_SYSVAR_ULONG( io_capacity, srv_io_capacity, PLUGIN_VAR_RQCMDARG, "Number of IOPs the server can do. Tunes the background IO rate", nullptr, @@ -23733,6 +23740,7 @@ static SYS_VAR *innobase_system_variables[] = { #endif /* UNIV_DEBUG */ MYSQL_SYSVAR(parallel_read_threads), MYSQL_SYSVAR(segment_reserve_factor), + MYSQL_SYSVAR(instant_ddl_strict_row_size), nullptr}; mysql_declare_plugin(innobase){ diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index e3ad510e2af..c52677a0228 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -698,6 +698,12 @@ struct dtuple_t { index record is built from a data tuple */ uint16_t info_bits; + /** Target row version for physical record creation. When set to a valid + version (not INVALID_ROW_VERSION), rec_convert_dtuple_to_rec_comp will use + this version instead of index->table->current_row_version. This is used + during rollback to restore records to their original physical format. */ + row_version_t row_version{INVALID_ROW_VERSION}; + /** Number of fields in dtuple */ uint16_t n_fields; diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic index db9d1a81f59..160e5802859 100644 --- a/storage/innobase/include/data0data.ic +++ b/storage/innobase/include/data0data.ic @@ -400,6 +400,7 @@ static inline dtuple_t *dtuple_create_from_mem(void *buf, ulint buf_size, tuple = (dtuple_t *)buf; tuple->info_bits = 0; + tuple->row_version = INVALID_ROW_VERSION; tuple->n_fields = n_fields; tuple->n_v_fields = n_v_fields; tuple->n_fields_cmp = n_fields; diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index f9261ffd58b..9e6156677a5 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -483,10 +483,13 @@ static inline ulint rec_get_converted_extra_size(ulint data_size, @param[in] fields array of data fields @param[in] n_fields number of data fields @param[out] extra extra size +@param[in] target_version target row version, INVALID_ROW_VERSION means + use current_row_version @return total size */ -ulint rec_get_converted_size_comp(const dict_index_t *index, ulint status, - const dfield_t *fields, ulint n_fields, - ulint *extra); +ulint rec_get_converted_size_comp( + const dict_index_t *index, ulint status, const dfield_t *fields, + ulint n_fields, ulint *extra, + row_version_t target_version = INVALID_ROW_VERSION); /** The following function returns the size of a data tuple when converted to a physical record. diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 8f0fce60aac..ad9c5e14d5b 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -766,7 +766,7 @@ static inline ulint rec_get_converted_size(const dict_index_t *index, if (dict_table_is_comp(index->table)) { return (rec_get_converted_size_comp( index, dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK, - dtuple->fields, dtuple->n_fields, nullptr)); + dtuple->fields, dtuple->n_fields, nullptr, dtuple->row_version)); } /* Record is in REDUNDANT format */ diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index 4ce1cf40713..f8e85e27457 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -582,6 +582,13 @@ struct upd_t { /** New value of info bits to record; default is 0. */ ulint info_bits; + /** Original row version from undo log. Used during rollback to restore + the physical record to its original row_version format, so that + rec_convert_dtuple_to_rec_comp writes only the fields visible in this + version. INVALID_ROW_VERSION means the version is unknown (old undo format + or table without row versions). */ + row_version_t old_row_version{INVALID_ROW_VERSION}; + /** Pointer to old row, used for virtual column update now. */ dtuple_t *old_vrow; diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index b759660a0e0..d1a6617c185 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -689,6 +689,8 @@ extern unsigned long long srv_stats_persistent_sample_pages; extern bool srv_stats_auto_recalc; extern bool srv_stats_include_delete_marked; +extern bool srv_instant_ddl_strict_row_size; + extern ulong srv_checksum_algorithm; extern double srv_max_buf_pool_modified_pct; diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index a478d4c19ab..16467eabe24 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -94,6 +94,9 @@ const byte *trx_undo_rec_get_row_ref( dtuple_t **ref, /*!< out, own: row reference */ mem_heap_t *heap); /*!< in: memory heap from which the memory needed is allocated */ + +struct type_cmpl_t; + /** Reads from an undo log update record the system field values of the old version. @return remaining part of undo log record after reading these values */ @@ -103,9 +106,14 @@ const byte *trx_undo_update_rec_get_sys_cols( general parameters */ trx_id_t *trx_id, /*!< out: trx id */ roll_ptr_t *roll_ptr, /*!< out: roll ptr */ - ulint *info_bits); /*!< out: info bits state */ - -struct type_cmpl_t; + ulint *info_bits, /*!< out: info bits state */ + const type_cmpl_t &type_cmpl, /*!< in: type compilation info, + used to determine if undo has + row_version */ + row_version_t *row_version = nullptr); /*!< out: original row version + from undo, INVALID_ROW_VERSION + if not present. nullptr if not + needed */ /** Builds an update vector based on a remaining part of an undo log record. @param[in] ptr Remaining part in update undo log record, after reading the row @@ -318,11 +326,19 @@ constexpr uint32_t TRX_UNDO_UPD_EXTERN = 128; constexpr uint32_t TRX_UNDO_INSERT_OP = 1; constexpr uint32_t TRX_UNDO_MODIFY_OP = 2; +/** Flags for the 1-byte undo record flag field (the byte after type_cmpl, +present when TRX_UNDO_MODIFY_BLOB is set). */ + +/** Bit 0: The undo record contains the original row_version (1 byte) +stored right after info_bits. Set when the table has row versions +(V2 INSTANT DDL). */ +constexpr uint8_t TRX_UNDO_FLAG_HAS_ROW_VERSION = 0x01; + /** The type and compilation info flag in the undo record for update. For easier understanding let the 8 bits be numbered as 7, 6, 5, 4, 3, 2, 1, 0. */ struct type_cmpl_t { - type_cmpl_t() : m_flag(0) {} + type_cmpl_t() : m_flag(0), m_undo_rec_flags(0) {} const byte *read(const byte *ptr) { m_flag = mach_read_from_1(ptr); @@ -354,8 +370,23 @@ struct type_cmpl_t { return (m_flag & TRX_UNDO_MODIFY_BLOB); } + /** Does the undo log record contain the original row_version byte + (stored after info_bits)? + @return true if row_version is present. */ + bool has_row_version() const { + return (m_undo_rec_flags & TRX_UNDO_FLAG_HAS_ROW_VERSION); + } + + /** Set the undo record flags byte. Called from trx_undo_rec_get_pars. */ + void set_undo_rec_flags(uint8_t flags) { m_undo_rec_flags = flags; } + + /** Get the undo record flags byte. */ + uint8_t undo_rec_flags() const { return m_undo_rec_flags; } + private: uint8_t m_flag; + /** The 1-byte undo record flag field (present when is_lob_undo()). */ + uint8_t m_undo_rec_flags; }; /** Reads from an undo log record the general parameters. diff --git a/storage/innobase/rem/rec.h b/storage/innobase/rem/rec.h index 36c3d00f27f..28329217257 100644 --- a/storage/innobase/rem/rec.h +++ b/storage/innobase/rem/rec.h @@ -827,7 +827,14 @@ static inline enum REC_INSERT_STATE get_rec_insert_state( if (is_versioned) { ut_a(is_valid_row_version(version)); if (version == 0) { - ut_ad(index->has_instant_cols()); + /* version=0 can appear in two cases: + 1. Upgraded table (has_instant_cols): row inserted after upgrade but + before any new-style INSTANT ADD/DROP. + 2. Rollback of a record that was inserted before INSTANT DDL: the undo + log stores version=0 for such records, and rollback restores them + with versioned bit + version=0. In this case only + has_row_versions() is true. */ + ut_ad(index->has_instant_cols() || index->has_row_versions()); rec_insert_state = INSERTED_AFTER_UPGRADE_BEFORE_INSTANT_ADD_NEW_IMPLEMENTATION; } else { @@ -1054,8 +1061,11 @@ static inline enum REC_INSERT_STATE rec_init_null_and_len_comp( /* Row inserted after first instant ADD/DROP COLUMN V2 */ ut_ad(index->table->has_row_versions()); } else { - /* Upgraded table. Row inserted before V2 INSTANT ADD/DROP */ - ut_ad(index->table->is_upgraded_instant()); + /* version=0 with versioned bit: either an upgraded table, or a + record restored by rollback that was originally inserted before + any INSTANT DDL. */ + ut_ad(index->table->is_upgraded_instant() || + index->table->has_row_versions()); } } #endif diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index cddf147cf31..ac033dfeadf 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -523,7 +523,10 @@ ulint rec_get_converted_size_comp( ulint status, /*!< in: status bits of the record */ const dfield_t *fields, /*!< in: array of data fields */ ulint n_fields, /*!< in: number of data fields */ - ulint *extra) /*!< out: extra size */ + ulint *extra, /*!< out: extra size */ + row_version_t target_version) /*!< in: target row version, + INVALID_ROW_VERSION means use + current_row_version */ { ulint size; ut_ad(n_fields > 0); @@ -553,9 +556,14 @@ ulint rec_get_converted_size_comp( ut_error; } + row_version_t rec_version = + (target_version != INVALID_ROW_VERSION) + ? target_version + : index->table->current_row_version; + return (size + rec_get_converted_size_comp_prefix_low( index, fields, n_fields, nullptr, extra, &status, false, - index->table->current_row_version)); + rec_version)); } /** Builds an old-style physical record out of a data tuple and @@ -802,9 +810,10 @@ static inline Rec_instant_state rec_convert_dtuple_to_rec_comp( index->table->is_upgraded_instant()); if (is_store_version(index, n_fields)) { - /* Store current version info in one byte. */ - rec_set_instant_row_version_new(rec, - index->table->current_row_version); + /* Store version info in one byte. Use the rec_version + parameter which may be the original version from undo + during rollback, not necessarily current_row_version. */ + rec_set_instant_row_version_new(rec, rec_version); /* Shift pointer to null byte before the version */ nulls -= 1; @@ -1062,14 +1071,21 @@ static rec_t *rec_convert_dtuple_to_rec_new(byte *buf, ulint status; rec_t *rec; + /* Determine the target row_version: use dtuple->row_version if set + (e.g. during rollback), otherwise use current_row_version. */ + row_version_t target_version = + (dtuple->row_version != INVALID_ROW_VERSION) + ? dtuple->row_version + : index->table->current_row_version; + status = dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK; rec_get_converted_size_comp(index, status, dtuple->fields, dtuple->n_fields, - &extra_size); + &extra_size, target_version); rec = buf + extra_size; auto rec_state = rec_convert_dtuple_to_rec_comp( rec, index, dtuple->fields, dtuple->n_fields, nullptr, status, false, - index->table->current_row_version); + target_version); /* Set the info bits of the record from dtuple */ rec_set_info_and_status_bits(rec, dtuple_get_info_bits(dtuple)); diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index fb3ef5bdf1f..52f336cb48a 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -866,7 +866,8 @@ static bool row_purge_parse_undo_rec(purge_node_t *node, return (false); } - ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits); + ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits, + type_cmpl); node->table = nullptr; node->trx_id = trx_id; diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 1ff96583164..7bcf797fc7d 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -1213,6 +1213,7 @@ static void row_undo_mod_parse_undo_rec(undo_node_t *node, THD *thd, ulint cmpl_info; bool dummy_extern; type_cmpl_t type_cmpl; + row_version_t old_row_version = INVALID_ROW_VERSION; auto ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info, &dummy_extern, @@ -1244,7 +1245,8 @@ static void row_undo_mod_parse_undo_rec(undo_node_t *node, THD *thd, clust_index = node->table->first_index(); - ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits); + ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits, + type_cmpl, &old_row_version); ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref), node->heap); @@ -1252,6 +1254,10 @@ static void row_undo_mod_parse_undo_rec(undo_node_t *node, THD *thd, info_bits, node->heap, &(node->update), nullptr, type_cmpl); + /* Store the original row_version from undo into the update vector, + so that rollback can restore the record to its original physical format. */ + node->update->old_row_version = old_row_version; + node->new_trx_id = trx_id; node->cmpl_info = cmpl_info; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 7e62b3d056f..4e2bc8a99f3 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -565,6 +565,7 @@ this many index pages, there are 2 ways to calculate statistics: unsigned long long srv_stats_transient_sample_pages = 8; bool srv_stats_persistent = true; bool srv_stats_include_delete_marked = false; +bool srv_instant_ddl_strict_row_size = true; unsigned long long srv_stats_persistent_sample_pages = 20; bool srv_stats_auto_recalc = true; diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 1e0abaf33b0..31f34a41461 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -579,7 +579,7 @@ const byte *trx_undo_rec_get_pars( undo_rec_flags = mach_read_from_1(ptr); ptr++; - ut_a(undo_rec_flags == 0x00); + type_cmpl.set_undo_rec_flags(undo_rec_flags); } *undo_no = mach_read_next_much_compressed(&ptr); @@ -1237,8 +1237,17 @@ static ulint trx_undo_page_report_modify( /* Introducing a change in undo log format. */ *type_cmpl_ptr |= TRX_UNDO_MODIFY_BLOB; - /* Introducing a new 1-byte flag. */ - *ptr++ = 0x00; + /* Introducing a new 1-byte flag. + Set TRX_UNDO_FLAG_HAS_ROW_VERSION if the table has row versions + (V2 INSTANT DDL), so that the undo record reader knows to expect + the row_version byte after info_bits. */ + { + uint8_t undo_rec_flags = 0x00; + if (index->has_row_versions()) { + undo_rec_flags |= TRX_UNDO_FLAG_HAS_ROW_VERSION; + } + *ptr++ = undo_rec_flags; + } ptr += mach_u64_write_much_compressed(ptr, trx->undo_no); @@ -1249,6 +1258,25 @@ static ulint trx_undo_page_report_modify( *ptr++ = (byte)rec_get_info_bits(rec, dict_table_is_comp(table)); + /* Store the original row_version if the table has row versions. + This allows rollback to restore the record to its original physical + format instead of always using current_row_version. */ + if (index->has_row_versions()) { + uint8_t rec_version; + if (rec_new_is_versioned(rec)) { + rec_version = + static_cast(rec_get_instant_row_version_new(rec)); + } else { + /* Record was inserted before any INSTANT DDL on this table, so it + has no version flag. Store version 0, which represents the original + table schema. On rollback, the record will be restored with + versioned bit set and version=0, so it is interpreted using only + the columns from the original table definition. */ + rec_version = 0; + } + *ptr++ = rec_version; + } + /* Store the values of the system columns */ field = rec_get_nth_field(nullptr, rec, offsets, index->get_sys_col_pos(DATA_TRX_ID), &flen); @@ -1708,12 +1736,27 @@ const byte *trx_undo_update_rec_get_sys_cols( general parameters */ trx_id_t *trx_id, /*!< out: trx id */ roll_ptr_t *roll_ptr, /*!< out: roll ptr */ - ulint *info_bits) /*!< out: info bits state */ + ulint *info_bits, /*!< out: info bits state */ + const type_cmpl_t &type_cmpl, /*!< in: type compilation info */ + row_version_t *row_version) /*!< out: original row version */ { /* Read the state of the info bits */ *info_bits = mach_read_from_1(ptr); ptr += 1; + /* Read the original row_version if present in this undo record */ + if (type_cmpl.has_row_version()) { + uint8_t raw_ver = mach_read_from_1(ptr); + ptr += 1; + if (row_version != nullptr) { + *row_version = static_cast(raw_ver); + } + } else { + if (row_version != nullptr) { + *row_version = INVALID_ROW_VERSION; + } + } + /* Read the values of the system columns */ *trx_id = mach_u64_read_next_compressed(&ptr); @@ -2465,6 +2508,7 @@ bool trx_undo_prev_version_build( ulint cmpl_info; bool dummy_extern; byte *buf; + row_version_t old_row_version = INVALID_ROW_VERSION; ut_ad(!rw_lock_own(&purge_sys->latch, RW_LOCK_S)); ut_ad(mtr_memo_contains_page(index_mtr, index_rec, MTR_MEMO_PAGE_S_FIX) || @@ -2512,7 +2556,8 @@ bool trx_undo_prev_version_build( return true; } - ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits); + ptr = trx_undo_update_rec_get_sys_cols(ptr, &trx_id, &roll_ptr, &info_bits, + type_cmpl, &old_row_version); /* (a) If a clustered index record version is such that the trx id stamp in it is bigger than purge_sys->view, then the @@ -2593,6 +2638,13 @@ bool trx_undo_prev_version_build( following call is safe. */ row_upd_index_replace_new_col_vals(entry, index, update, heap); + /* Use the original row_version from undo to rebuild the old version + record in the correct physical format. This ensures MVCC reads see + the record with only the columns visible in the original version. */ + if (old_row_version != INVALID_ROW_VERSION) { + entry->row_version = old_row_version; + } + buf = static_cast( mem_heap_alloc(heap, rec_get_converted_size(index, entry)));