Bug #113051 Skip instant DDL for empty tables to save row versions
Submitted: 10 Nov 2023 20:16 Modified: 16 Jan 3:51
Reporter: Marc Reilly Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: DDL Severity:S4 (Feature request)
Version:8.0.35 OS:Any
Assigned to: CPU Architecture:Any
Tags: DDL, instant ddl

[10 Nov 2023 20:16] Marc Reilly
Description:
When adding a column to an empty table InnoDB should skip INSTANT DDL. I don't think there is a real benefit here to using INSTANT as inplace will be just as fast. The side effect here is that when using INSTANT it burns a row version which contributes to the max number of instant row versions a innodb table can have(64).

In isolation this should be ok, but If a user is applying frequent DDL changes this can contribute to hitting the 64 column limit on an existing table.

This is a also a common method of creating new tables for online schema change tools or tools where schema changes may be versioned and incrementally deployed e.g.  create table and apply incremental changes on top of them.

How to repeat:
mysql [localhost:8035] {msandbox} (test) > select @@version,@@build_id;
+-----------+------------------------------------------+
| @@version | @@build_id                               |
+-----------+------------------------------------------+
| 8.0.35    | 6d2f8b8d1160e6ff611567f97b9c5eba916143aa |
+-----------+------------------------------------------+
1 row in set (0.00 sec)

mysql [localhost:8035] {msandbox} (test) > create table test(id int);
Query OK, 0 rows affected (0.00 sec)

mysql [localhost:8035] {msandbox} (test) > select * from information_schema.innodb_tables where name like 'test/%';
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
| TABLE_ID | NAME      | FLAG | N_COLS | SPACE | ROW_FORMAT | ZIP_PAGE_SIZE | SPACE_TYPE | INSTANT_COLS | TOTAL_ROW_VERSIONS |
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
|     1064 | test/test |   33 |      4 |     2 | Dynamic    |             0 | Single     |            0 |                  0 |
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
1 row in set (0.01 sec)

mysql [localhost:8035] {msandbox} (test) > alter table test add column name varchar(20);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql [localhost:8035] {msandbox} (test) > select * from information_schema.innodb_tables where name like 'test/%';
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
| TABLE_ID | NAME      | FLAG | N_COLS | SPACE | ROW_FORMAT | ZIP_PAGE_SIZE | SPACE_TYPE | INSTANT_COLS | TOTAL_ROW_VERSIONS |
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
|     1064 | test/test |   33 |      5 |     2 | Dynamic    |             0 | Single     |            0 |                  1 |
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
1 row in set (0.00 sec)

Suggested fix:
Revert to INPLACE instead of INSTANT for tables which contain no data.
[13 Nov 2023 6:33] MySQL Verification Team
Hello Marc,

Thank you for the reasonable feature request.

regards,
Umesh
[16 Jan 3:51] Philip Olson
Posted by developer:
 
Fixed as of the upcoming MySQL Server 8.0.41, 8.4.4, and 9.2.0 releases, and here's the proposed changelog entry from the documentation team for review:

Executing ALTER TABLE ... ADD|DROP COLUMN against an empty table now uses
the INPLACE algorithm by default instead of INSTANT. This change means the
row version is no longer incremented for these simple operations.

Thank you for the bug report.