适用范围
社区版MySQL8.0.29/30/31
问题概述
在使用XtraBackup进行对MySQL 8.0.30 或 8.0.31进行数据库备份时无法正常备份,报如下错误:
[root@c1 bin]# ./xtrabackup --defaults-file=/data/mysql/mysql8030/my8030.cnf --backup --target-dir=/data/backup/backup8030 --user=root --password=mysql8030 -S /lvdata/mysql/8030/run/mysql.sock
2023-03-13T16:49:33.860824+08:00 0 [Note] [MY-011825] [Xtrabackup] recognized server arguments: --server-id=128 --datadir=/lvdata/mysql/8030/data --log_bin=/lvdata/mysql/8030/binlogs/mysql-bin --tmpdir=/lvdata/mysql/8030/tmp --innodb_buffer_pool_size=128M --innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend --innodb_flush_method=O_DIRECT
2023-03-13T16:49:33.863903+08:00 0 [Note] [MY-011825] [Xtrabackup] recognized client arguments: --port=8030 --socket=/lvdata/mysql/8030/run/mysql.sock --backup=1 --target-dir=/data/backup/backup8030 --user=root --password=* --socket=/lvdata/mysql/8030/run/mysql.sock
./xtrabackup version 8.0.30-23 based on MySQL server 8.0.30 Linux (x86_64) (revision id: 873b467185c)
230313 16:49:33 version_check Connecting to MySQL server with DSN 'dbi:mysql:;mysql_read_default_group=xtrabackup;port=8030;mysql_socket=/lvdata/mysql/8030/run/mysql.sock' as 'root' (using password: YES).
230313 16:49:33 version_check Connected to MySQL server
230313 16:49:36 version_check Done.
2023-03-13T16:49:36.989037+08:00 0 [Note] [MY-011825] [Xtrabackup] Connecting to MySQL server host: localhost, user: root, password: set, port: 8030, socket: /lvdata/mysql/8030/run/mysql.sock
2023-03-13T16:49:37.000662+08:00 0 [Note] [MY-011825] [Xtrabackup] Using server version 8.0.30
2023-03-13T16:49:37.008484+08:00 0 [Note] [MY-011825] [Xtrabackup] Executing LOCK INSTANCE FOR BACKUP ...
2023-03-13T16:49:37.019793+08:00 0 [ERROR] [MY-011825] [Xtrabackup] Found tables with row versions due to INSTANT ADD/DROP columns
2023-03-13T16:49:37.019845+08:00 0 [ERROR] [MY-011825] [Xtrabackup] This feature is not stable and will cause backup corruption.
2023-03-13T16:49:37.019852+08:00 0 [ERROR] [MY-011825] [Xtrabackup] Please check https://docs.percona.com/percona-xtrabackup/8.0/em/instant.html for more details.
2023-03-13T16:49:37.019874+08:00 0 [ERROR] [MY-011825] [Xtrabackup] Tables found:
2023-03-13T16:49:37.019883+08:00 0 [ERROR] [MY-011825] [Xtrabackup] my2/test2
2023-03-13T16:49:37.019887+08:00 0 [ERROR] [MY-011825] [Xtrabackup] my2/t1
2023-03-13T16:49:37.019891+08:00 0 [ERROR] [MY-011825] [Xtrabackup] Please run OPTIMIZE TABLE or ALTER TABLE ALGORITHM=COPY on all listed tables to fix this issue.
[root@c1 bin]#
重点查看error报错部分信息:
Found tables with row versions due to INSTANT ADD/DROP columns
This feature is not stable and will cause backup corruption.
Please check https://docs.percona.com/percona-xtrabackup/8.0/em/instant.html for more details.
Tables found:
my2/test2
my2/t1
Please run OPTIMIZE TABLE or ALTER TABLE ALGORITHM=COPY on all listed tables to fix this issue.
从日志中提示发现有表因为曾经做过增加或者删除列,导致所谓的row version(行版本)问题,但是这个特性不稳定导致备份损坏(backup corruption)。
我们查一下这两个表:
root@127.0.0.1:my2 05:13:28 >SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE TOTAL_ROW_VERSIONS > 0;
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
| TABLE_ID | NAME | FLAG | N_COLS | SPACE | ROW_FORMAT | ZIP_PAGE_SIZE | SPACE_TYPE | INSTANT_COLS | TOTAL_ROW_VERSIONS |
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
| 1124 | my2/test2 | 33 | 7 | 63 | Dynamic | 0 | Single | 0 | 1 |
| 1172 | my2/t1 | 33 | 8 | 111 | Dynamic | 0 | Single | 0 | 1 |
+----------+-----------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
2 rows in set (0.00 sec)
说明:最后一列 TOTAL_ROW_VERSIONS都为1,经验证只要进行过一次add column 或者drop column该值就会加1.
问题原因
在MySQL 8.0.29 之前,在线 DDL 操作中即时添加列只能添加在表的最后一列,对于在某个具体列后面快速添加列很不方便,从MySQL 8.0.29 开始扩展了对 ALTER TABLE … ALGORITHM=INSTANT 的支持:用户可以在表的任何位置即时添加列、即时删除列、添加列时评估行大小限制。
每次即时添加或删除列都会创建一个新的行版本。MySQL 8.0.29 在 INFORMATION_SCHEMA.INNODB_TABLES 表中添加了一个新的列 TOTAL_ROW_VERSIONS 列来跟踪行版本的数量,每个表最多允许 64 行版本。
以上这个在任意位置加列/删列的功能这算是从8.0.29以后的一个新特性,但就是因为这个新特性,InnoDB redo log 格式对于所有 DML 操作都发生了变化。新的 redo 日志格式引入了一个设计缺陷,会导致 instant add/drop columns 的表数据损坏。据说这个缺陷已在 Percona 版 MySQL 8.0.29 中已修复,但在当前的社区版本 MySQL 8.0.29 ,8.0.30甚至8.0.31版本中仍然有缺陷。
由于 XtraBackup 无法处理社区版生成的损坏的 redo log ,因此,如果 XtraBackup 8.0.29/30/31 版本检测到具有 INSTANT ADD/DROP 列的表,它将不会进行备份,并且会生成错误信息,列出受影响表的列表并提供将它们转换为常规表的说明。
解决方案
经查询,这属于Percona XtraBackup的Bug,但是官方并没有明确升级为Bug,只是作为Issues(问题)列出,解决方式参考错误提示进行修复即可,即将涉及到的表进行一次 OPTIMIZE TABLE 操作后,再进行备份,问题消失备份正常。
另外经测试,在最新版本MySQL社区版8.0.32中这个问题已经消失,同时在用Percona XtraBackup-8.0.32-25版本备份社区版MySQL8.0.32过程中没有出现上述问题,一切正常,本次问题只涉及到社区版MySQL8.0.29,8.0.30和8.0.31。
参考文档
https://docs.percona.com/percona-xtrabackup/8.0/em/instant.html