Bug #115194 Incorrect description of Online DDL Operations in reference manual
Submitted: 3 Jun 2024 6:24 Modified: 3 Jun 2024 9:35
Reporter: Brian Yue (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Documentation Severity:S3 (Non-critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any
Tags: Online DDL, Reference Manual

[3 Jun 2024 6:24] Brian Yue
Description:
Hello,
  About "Column Operations" part in chapter 17.12.1 Online DDL Operations of reference manual, "Permits Concurrent DML" attribute for operation ""Dropping the column default value is writen as "YES", actually it's not exact.
  The following is described in the same page of reference manual:
"""
  For VARCHAR columns of 0 to 255 bytes in size, one length byte is required to encode the value. For VARCHAR columns of 256 bytes in size or more, two length bytes are required. As a result, in-place ALTER TABLE only supports increasing VARCHAR column size from 0 to 255 bytes, or from 256 bytes to a greater size. In-place ALTER TABLE does not support increasing the size of a VARCHAR column from less than 256 bytes to a size equal to or greater than 256 bytes. In this case, the number of required length bytes changes from 1 to 2, which is only supported by a table copy (ALGORITHM=COPY). 
"""

  So, if the size of VARCHAR column is extended from less than 256 bytes to a size equal to or greater than 256 bytes, copy algorithm is used, and it will not be a online operation, which means COPY algorithm is used and EXCLUSIVE mdl lock is aquired. Here is the illustration:

[session 1]

create database ddl;
use ddl;
create table ddl.t1 (c1 varchar(40) charset utf8mb4);

mysql> insert into t1 values ('A'),('A'),('A'),('A'),('A'),('A'),('A'),('A');
Query OK, 8 rows affected (0.01 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> insert into t1 select a.c1 from t1 a join t1 b;
Query OK, 64 rows affected (0.00 sec)
Records: 64  Duplicates: 0  Warnings: 0

mysql> insert into t1 select a.c1 from t1 a join t1 b;
Query OK, 5184 rows affected (0.03 sec)
Records: 5184  Duplicates: 0  Warnings: 0

mysql> insert into t1 select a.c1 from t1 a join t1 b;
Query OK, 27625536 rows affected (1 min 56.49 sec)
Records: 27625536  Duplicates: 0  Warnings: 0

mysql> alter table t1 change column c1 c1 varchar(400);

While the alter table is in execution, operate session 2:

[session 2]

mysql> set session lock_wait_timeout = 5;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into ddl.t1 values ('CC');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> show processlist;
+----+-----------------+-----------+------+---------+---------+------------------------+-------------------------------------------------+
| Id | User            | Host      | db   | Command | Time    | State                  | Info                                            |
+----+-----------------+-----------+------+---------+---------+------------------------+-------------------------------------------------+
|  5 | event_scheduler | localhost | NULL | Daemon  | 1174797 | Waiting on empty queue | NULL                                            |
| 61 | root            | localhost | ddl  | Sleep   |    1983 |                        | NULL                                            |
| 75 | root            | localhost | ddl  | Query   |      17 | copy to tmp table      | alter table t1 change column c1 c1 varchar(400) |
| 79 | root            | localhost | ddl  | Query   |       0 | init                   | show processlist                                |
+----+-----------------+-----------+------+---------+---------+------------------------+-------------------------------------------------+
4 rows in set, 1 warning (0.00 sec)

mysql> insert into ddl.t1 values ('CC');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

we can see that concurrent DML is not permitted when the DDL is in execution, attemption of DML operation result in  Lock wait timeout error. Alse, State of DDL is "copy to tmp table" show that it's rebulding a new table but "Rebuilds Table" attribute of "Extending VARCHAR column size" is writen as "No".

So I believe operation of "Extending VARCHAR column size" from less than 256 bytes to a size equal to or greater than 256 bytes  uses copy algrithm, needs to Rebuild table, and dose not permit concurrent DML, and of course not modify metadata only.

How to repeat:
[session 1]

create database ddl;
use ddl;
create table ddl.t1 (c1 varchar(40) charset utf8mb4);

mysql> insert into t1 values ('A'),('A'),('A'),('A'),('A'),('A'),('A'),('A');
Query OK, 8 rows affected (0.01 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> insert into t1 select a.c1 from t1 a join t1 b;
Query OK, 64 rows affected (0.00 sec)
Records: 64  Duplicates: 0  Warnings: 0

mysql> insert into t1 select a.c1 from t1 a join t1 b;
Query OK, 5184 rows affected (0.03 sec)
Records: 5184  Duplicates: 0  Warnings: 0

mysql> insert into t1 select a.c1 from t1 a join t1 b;
Query OK, 27625536 rows affected (1 min 56.49 sec)
Records: 27625536  Duplicates: 0  Warnings: 0

mysql> alter table t1 change column c1 c1 varchar(400);

While the alter table is in execution, operate session 2:

[session 2]

mysql> set session lock_wait_timeout = 5;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into ddl.t1 values ('CC');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> show processlist;
+----+-----------------+-----------+------+---------+---------+------------------------+-------------------------------------------------+
| Id | User            | Host      | db   | Command | Time    | State                  | Info                                            |
+----+-----------------+-----------+------+---------+---------+------------------------+-------------------------------------------------+
|  5 | event_scheduler | localhost | NULL | Daemon  | 1174797 | Waiting on empty queue | NULL                                            |
| 61 | root            | localhost | ddl  | Sleep   |    1983 |                        | NULL                                            |
| 75 | root            | localhost | ddl  | Query   |      17 | copy to tmp table      | alter table t1 change column c1 c1 varchar(400) |
| 79 | root            | localhost | ddl  | Query   |       0 | init                   | show processlist                                |
+----+-----------------+-----------+------+---------+---------+------------------------+-------------------------------------------------+
4 rows in set, 1 warning (0.00 sec)

mysql> insert into ddl.t1 values ('CC');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
[3 Jun 2024 9:35] MySQL Verification Team
Hi Mr. Yue,

Thank you for your documentation bug report.

We agree with you that our documentation is incorrect in the part that you describe.

Verified as a Documentation bug for the version 8.0 and higher.