Bug #110702 In-place upgrading from 5.7.41 to 8.0.32, a table with FK's data is broken
Submitted: 15 Apr 2023 5:47 Modified: 17 Apr 2023 7:10
Reporter: Tsubasa Tanaka (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Data Dictionary Severity:S2 (Serious)
Version:8.0.32 OS:CentOS (7.9)
Assigned to: CPU Architecture:x86
Tags: Contribution

[15 Apr 2023 5:47] Tsubasa Tanaka
Description:
The operation of "table which has Foreign Key(child table)" + "Inplace upgrade from 5.7 to 8.0" + "Add instant column" breaks data in table.

See How to repeat.

How to repeat:
By using docker.

### Empty new directory
mkdir /tmp/test

### Initialize by MySQL 5.7.41 on docker
sudo docker run -d -P  --mount type=bind,src=/tmp/test,dst=/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -e MYSQL_ROOT_PASSWORD="""" -e MYSQL_ROOT_HOST=""%"" --restart=on-failure mysql/mysql-server:5.7.41

### Access the MySQL 5.7.41 and make tables and rows
mysql -h 172.17.0.2 -uroot
CREATE DATABASE d1;
CREATE TABLE d1.parent (num int PRIMARY KEY, val varchar(32));
CREATE TABLE d1.child (num int PRIMARY KEY, val varchar(32), FOREIGN KEY (num) REFERENCES parent(num));
INSERT INTO d1.parent VALUES (1, 'one');
INSERT INTO d1.child VALUES (1, 'one');

### Turn off 5.7 and inplace-upgrade by 8.0.32
SHUTDOWN;
quit

sudo docker run -d -P  --mount type=bind,src=/tmp/test,dst=/var/lib/mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -e MYSQL_ROOT_PASSWORD="""" -e MYSQL_ROOT_HOST=""%"" --restart=on-failure mysql/mysql-server:8.0.32

### Access 8.0.32 after DD upgrade
mysql -h 172.17.0.2 -uroot

mysql> SELECT * FROM d1.child;
+-----+------+
| num | val  |
+-----+------+
|   1 | one  |
+-----+------+
1 row in set (0.01 sec)

mysql> ALTER TABLE d1.child ADD col INT, ALGORITHM= INSTANT;
Query OK, 0 rows affected (0.06 sec)
Records: 0  Duplicates: 0  Warnings: 0

### After INSTANT ADD COLUMN, data is broken
mysql> SELECT * FROM d1.child;
+-----+------+------+
| num | val  | col  |
+-----+------+------+
|   1 | ▒    | NULL |
+-----+------+------+
1 row in set (0.00 sec)

mysql> CHECK TABLE d1.child;
+----------+-------+----------+---------------------------------------------------+
| Table    | Op    | Msg_type | Msg_text                                          |
+----------+-------+----------+---------------------------------------------------+
| d1.child | check | Warning  | InnoDB: The B-tree of index PRIMARY is corrupted. |
| d1.child | check | error    | Corrupt                                           |
+----------+-------+----------+---------------------------------------------------+
2 rows in set (0.01 sec)

### Error-log
2023-04-15T05:45:10.860817455Z 2023-04-15T05:45:10.854779Z 11 [ERROR] [MY-012734] [InnoDB] Summed data size 24, returned by func 27
2023-04-15T05:45:10.860862132Z 2023-04-15T05:45:10.860725Z 11 [ERROR] [MY-012738] [InnoDB] Apparent corruption in space 26 page 3 index `PRIMARY`
2023-04-15T05:45:10.860962522Z 2023-04-15T05:45:10.860761Z 11 [ERROR] [MY-013050] [InnoDB] In page 3 of index `PRIMARY` of table `d1`.`child`
[17 Apr 2023 2:11] Tsubasa Tanaka
I confirmed

- Restarting 8.0.32 before ALTER TABLE avoids this problem.
- ALTER TABLE d1.child ADD col INT, ALGORITHM= INPLACE (without RESTART) avoids this problem
[17 Apr 2023 7:10] MySQL Verification Team
Hello tanaka-San,

Thank you for the report and feedback.

regards,
Umesh
[2 Dec 2024 12:00] li linhua
fix fk table may corrupt if upgrade from 5.7 to 8.0 and use  instant add column

(*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

Contribution: fix_fk_table_corrupt_when_upgrade_from_57.patch (application/octet-stream, text), 2.02 KiB.