Description:
An INPLACE null rebuild of an InnoDB table that already has a spatial index can
build a corrupt R-tree and abort a debug server.
The issue was reproduced from unmodified MySQL Community Server 9.7.2 source,
commit `008e09c2834b98143a8c067d4d225c90953050cf` (the `mysql-9.7.2` tag and
`upstream/9.7` point to the same commit). The source tree has no local
changes in the InnoDB implementation. It was built with `WITH_DEBUG=ON` and
GCC 13.3.1 on Linux x86_64. The local binary reports `9.7.2-rds-debug`
because of a build-only version suffix; no downstream source patch is involved.
The MTR server configuration uses `--innodb_buffer_pool_size=5M`.
The reproducer was run five times serially. All five runs reached the same
failure. There is no concurrent DML, delete, purge, or schema change while the
rebuild is paused.
`ALTER TABLE ... ENGINE=InnoDB, ALGORITHM=INPLACE` is a supported null rebuild
operation, and the spatial column is declared `NOT NULL` as required for an
InnoDB spatial index. The operation should complete and `CHECK TABLE t1`
should report `OK`. Instead, InnoDB detects records in the wrong order in
`sp_g` and the debug validation aborts the server:
```
[ERROR] [MY-012726] [InnoDB] Records in wrong order on space 7 page 5 index `sp_g`
[ERROR] [MY-012738] [InnoDB] Apparent corruption in space 7 page 5 index `sp_g`
[ERROR] [MY-013050] [InnoDB] In page 5 of index `sp_g` of table `test`.`#sql-...`
[ERROR] [MY-013183] [InnoDB] Assertion failure: ddl0ctx.cc:523:
err != DB_SUCCESS || loader.validate_indexes()
#0 print_fatal_signal
#1 my_server_abort
#2 my_abort
#3 ut_dbg_assertion_failed
#4 ddl::Context::build() at storage/innobase/ddl/ddl0ctx.cc:523
#5 ha_innobase::inplace_alter_table_impl()
```
The R-tree validation output also shows the appended primary-key field reading
as `0x78787878` (`xxxx`), rather than an integer primary-key value. This is
data from the LOB workload, not a valid primary-key value.
How to repeat:
Build a debug MySQL Community Server 9.7.2 server. Start the MTR server with
`--innodb_buffer_pool_size=5M`. The following is the complete test body:
```
--source include/have_debug.inc
--source include/have_debug_sync.inc
CREATE TABLE t1 (
id INT NOT NULL AUTO_INCREMENT,
c LONGBLOB,
pad CHAR(60) NOT NULL,
g LINESTRING NOT NULL,
PRIMARY KEY (id),
SPATIAL KEY sp_g (g)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
INSERT INTO t1 (c, pad, g)
VALUES
(REPEAT('x', 6 * 1024 * 1024), REPEAT('a', 60),
ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')),
(REPEAT('x', 6 * 1024 * 1024), REPEAT('b', 60),
ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')),
(REPEAT('x', 6 * 1024 * 1024), REPEAT('c', 60),
ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)'));
--connect (con1, localhost, root,,)
SET DEBUG='+d,ddl_buf_add_two';
SET DEBUG_SYNC='ddl_bulk_inserter_latches_released SIGNAL ddl_latches_released WAIT_FOR ddl_continue';
--send ALTER TABLE t1 ENGINE=InnoDB, ALGORITHM=INPLACE
--connection default
SET DEBUG_SYNC='now WAIT_FOR ddl_latches_released';
SET DEBUG_SYNC='now SIGNAL ddl_continue';
--connection con1
--reap
CHECK TABLE t1;
```
The companion MTR option file contains:
```
--innodb_buffer_pool_size=5M
```
On the affected debug build, the client receives:
```
ERROR HY000: Lost connection to MySQL server during query
```
and the server error log contains the corruption messages and assertion shown
in the Description section. Repeating the test serially five times produced the
same assertion in all five runs.
Expected result: the ALTER succeeds and `CHECK TABLE t1` reports `status OK`.
Actual result: the ALTER aborts the debug server after `sp_g` has been built
with invalid key data. On a non-debug build, the same path can leave a corrupt
spatial index instead of stopping at the debug validation assertion.
Description: An INPLACE null rebuild of an InnoDB table that already has a spatial index can build a corrupt R-tree and abort a debug server. The issue was reproduced from unmodified MySQL Community Server 9.7.2 source, commit `008e09c2834b98143a8c067d4d225c90953050cf` (the `mysql-9.7.2` tag and `upstream/9.7` point to the same commit). The source tree has no local changes in the InnoDB implementation. It was built with `WITH_DEBUG=ON` and GCC 13.3.1 on Linux x86_64. The local binary reports `9.7.2-rds-debug` because of a build-only version suffix; no downstream source patch is involved. The MTR server configuration uses `--innodb_buffer_pool_size=5M`. The reproducer was run five times serially. All five runs reached the same failure. There is no concurrent DML, delete, purge, or schema change while the rebuild is paused. `ALTER TABLE ... ENGINE=InnoDB, ALGORITHM=INPLACE` is a supported null rebuild operation, and the spatial column is declared `NOT NULL` as required for an InnoDB spatial index. The operation should complete and `CHECK TABLE t1` should report `OK`. Instead, InnoDB detects records in the wrong order in `sp_g` and the debug validation aborts the server: ``` [ERROR] [MY-012726] [InnoDB] Records in wrong order on space 7 page 5 index `sp_g` [ERROR] [MY-012738] [InnoDB] Apparent corruption in space 7 page 5 index `sp_g` [ERROR] [MY-013050] [InnoDB] In page 5 of index `sp_g` of table `test`.`#sql-...` [ERROR] [MY-013183] [InnoDB] Assertion failure: ddl0ctx.cc:523: err != DB_SUCCESS || loader.validate_indexes() #0 print_fatal_signal #1 my_server_abort #2 my_abort #3 ut_dbg_assertion_failed #4 ddl::Context::build() at storage/innobase/ddl/ddl0ctx.cc:523 #5 ha_innobase::inplace_alter_table_impl() ``` The R-tree validation output also shows the appended primary-key field reading as `0x78787878` (`xxxx`), rather than an integer primary-key value. This is data from the LOB workload, not a valid primary-key value. How to repeat: Build a debug MySQL Community Server 9.7.2 server. Start the MTR server with `--innodb_buffer_pool_size=5M`. The following is the complete test body: ``` --source include/have_debug.inc --source include/have_debug_sync.inc CREATE TABLE t1 ( id INT NOT NULL AUTO_INCREMENT, c LONGBLOB, pad CHAR(60) NOT NULL, g LINESTRING NOT NULL, PRIMARY KEY (id), SPATIAL KEY sp_g (g) ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC; INSERT INTO t1 (c, pad, g) VALUES (REPEAT('x', 6 * 1024 * 1024), REPEAT('a', 60), ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')), (REPEAT('x', 6 * 1024 * 1024), REPEAT('b', 60), ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')), (REPEAT('x', 6 * 1024 * 1024), REPEAT('c', 60), ST_GeomFromText('LINESTRING(0 0, 1 1, 2 2)')); --connect (con1, localhost, root,,) SET DEBUG='+d,ddl_buf_add_two'; SET DEBUG_SYNC='ddl_bulk_inserter_latches_released SIGNAL ddl_latches_released WAIT_FOR ddl_continue'; --send ALTER TABLE t1 ENGINE=InnoDB, ALGORITHM=INPLACE --connection default SET DEBUG_SYNC='now WAIT_FOR ddl_latches_released'; SET DEBUG_SYNC='now SIGNAL ddl_continue'; --connection con1 --reap CHECK TABLE t1; ``` The companion MTR option file contains: ``` --innodb_buffer_pool_size=5M ``` On the affected debug build, the client receives: ``` ERROR HY000: Lost connection to MySQL server during query ``` and the server error log contains the corruption messages and assertion shown in the Description section. Repeating the test serially five times produced the same assertion in all five runs. Expected result: the ALTER succeeds and `CHECK TABLE t1` reports `status OK`. Actual result: the ALTER aborts the debug server after `sp_g` has been built with invalid key data. On a non-debug build, the same path can leave a corrupt spatial index instead of stopping at the debug validation assertion.