[MDEV-32167] Table cannot be backed up after a innodb import tablespace for tables without foreign key Created: 2023-09-14  Updated: 2024-01-08  Resolved: 2024-01-08

Status: Closed
Project: MariaDB Server
Component/s: Backup, mariabackup, Server, Storage Engine - InnoDB
Affects Version/s: 10.6.15, 10.11.5
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: Harry Pask Assignee: Marko Mäkelä
Resolution: Incomplete Votes: 0
Labels: None
Environment:

CentOS 7


Attachments: PNG File Before and after import.png     File all-dbs.sql     File grabresults.sql     File mariabackup.bash     File prepare.bash     File singledb.bash    

 Description   

Hi there,

I am currently making a mariabackup script for full and incremental backups along with a prepare script to loop through the compressed incrementals and apply to the full. I am also making a script to automate the process for a single DB restore from a full mariabackup. I came up with the scripts needed to make it easier for this blog post from 2018 which can be found here, my SQL script can be found here and the order you run them to take the full backup and restore a single Database.

The issue I have came across is after I generate the .cfg files from the full backup and then restore a single DB with my bash script which does so just fine. When I run my backup script again and prepare the backup with the new incremental the .ibd and .cfg files aren't generated for tables that didn't have a foreign key on them. I have tested this to make sure by running the above process by restoring from a older backup, adding a foreign key to the table, running the same process. I found that the newly added foreign key makes it so the new backup can generate the .ibd and .cfg files so the table isn't corrupted after innodb import statement. The only tables corrupted are the ones without foreign keys I have tried running FLUSH TABLES and FLUSH TABLES .. FOR EXPORT with no luck in sorting this.

Also, I first tried this on 10.6.15 then upgraded to 10.11.5 so this bug is there for all versions.

I have also tried restarted mariadb after the import then ran a backup with no luck, after I run a backup (incremental) then do a full restore from this incremental applied to the fullbackup it says the table isn't registered in the InnoDB engine.

In the screenshot attached you should be able to see that at the vip table (prepared with incremental, backup before innodb import) and at the bottom the same table (after importing innodb tables, after running a backup and preparing the backup with --export for .cfg files)

Nothing in the prepare logs say anything to suggest the backup is broken or the .cfg cannot be generated



 Comments   
Comment by Harry Pask [ 2023-09-14 ]

This is also the case in 11.2.1 with the improvements of MDEV-26137

Comment by Marko Mäkelä [ 2023-09-27 ]

Can you please post a set of files that demonstrates this problem when executed against a newly initialized server? For example, include one or more SQL files that will be fed to the mariadb client. The test could be driven by a number of Bourne shell commands.

Comment by Harry Pask [ 2023-09-27 ]

Thanks for getting back to me. Sure, please see attached a number of files. After doing this on clean install with a new datadir, with a dump file imported into mariadb this is still the case.

I have attached the scripts I have made.

I have set the backup dir to be the following with the date being the parent folder for each days of the backup /media/backups/DATA_OF_BACKUP. Also, in the script I have attached the permissions for the user

Once you have imported the fire.sql into MariaDB and added the required user run the mariabackup.bash script bash mariabackup.bash (run twice to get a incremental aswell). Next, prepare the backup with the prepare.bash script run as so bash prepare.bash /media/backups/2023-09-27/ --export this will prepare the full backup and apply any incremental backups to the full backup in order, it will also run another prepare with the --export option.

Once the backup is prepared, run the singledb.bash in the same directory as the grabresults.sql which contains the SQL concat statements that will be imported to Mariadb and output four files to /tmp/, it will then run the process to run the four files in the correct order. To run this script do the following bash singledb.bash /media/backups/2023-09-27/fullbackup fire /media/backups/2023-09-27/tablestructure/fire/2023-09-27-TIMEOFBACKUP.sql This should run fine. Next, repeat the process (Mariabackup.bash > prepare.bash > singledb.bash) on the second run it should fail with the following:

cp: cannot stat ‘/media/backups/2023-09-27/fullbackup//fire/*.cfg’: No such file or directory
ERROR 1030 (HY000) at line 1: Got error 194 "Tablespace is missing for a table" from storage engine InnoDB

You will get this error as mariabackup wasn't able to export the .cfg files from the new incremental backup

Please let me know if you run into any issues

all-dbs.sql grabresults.sql mariabackup.bash prepare.bash singledb.bash

Comment by Harry Pask [ 2023-10-27 ]

Hello,

Is this currently being investigated?

Comment by Marko Mäkelä [ 2023-11-27 ]

I had some higher-priority tasks until now. I will check this next.

Comment by Marko Mäkelä [ 2023-12-01 ]

I had some trouble executing the singledb.bash script. It would generate a grabresults2.sql file but somehow fail to execute it as intended, because none of its output files in /tmp would be created. When I execute SQL statements from grabresults2.sql manually, the output files will be created just fine.

I would also like to note that with MDEV-26137 in MariaDB Server 11.2, you can import tables based on .frm files. The CREATE TABLE and ALTER TABLE…DISCARD TABLESPACE steps would be omitted in that case.

Also, I would advise against using bash in scripts. A more restricted implementation of the POSIX /bin/sh (such as dash) should open a smaller attack surface to security bugs like Shellshock.

I can spot one logic flaw in the script. It’s dropping all secondary indexes (why?), then discarding the tablespace, then copying the .cfg and .ibd files, and finally importing the tablespace. In this way, there will be a mismatch regarding the secondary indexes. It would seem to me that the import operation would simply be rejected in this case:

--source include/have_innodb.inc
 
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, INDEX(b)) ENGINE=InnoDB;
CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
ALTER TABLE t2 DISCARD TABLESPACE ;
FLUSH TABLES t1 FOR EXPORT;
let $datadir=`select @@datadir`;
--copy_file $datadir/test/t1.ibd $datadir/test/t2.ibd
--move_file $datadir/test/t1.cfg $datadir/test/t2.cfg
UNLOCK TABLES;
--error ER_TABLE_SCHEMA_MISMATCH
ALTER TABLE t2 IMPORT TABLESPACE;
DROP TABLE t2,t1;

The above .test file that I tried out resulted in the expected error. The table t2 would be missing a tablespace. I think that this must be happening here as well.

If the issue that is being worked around is that IMPORT TABLESPACE is disallowed when FOREIGN KEY constraints exist, then it should suffice to drop and create the FOREIGN KEY constraints only. Neither the .cfg files nor the .ibd files should contain any information about FOREIGN KEY. I tested this as well:

--source include/have_innodb.inc
 
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, INDEX(b),
CONSTRAINT f1 FOREIGN KEY (a) REFERENCES t) ENGINE=InnoDB;
CREATE TABLE t2 (a INT PRIMARY KEY, b INT, INDEX(b)) ENGINE=InnoDB;
ALTER TABLE t2 DISCARD TABLESPACE ;
FLUSH TABLES t1 FOR EXPORT;
let $datadir=`select @@datadir`;
--copy_file $datadir/test/t1.ibd $datadir/test/t2.ibd
--move_file $datadir/test/t1.cfg $datadir/test/t2.cfg
UNLOCK TABLES;
ALTER TABLE t2 IMPORT TABLESPACE;
ALTER TABLE t2 ADD CONSTRAINT f2 FOREIGN KEY(a) REFERENCES t(a);
SHOW CREATE TABLE t1;
SHOW CREATE TABLE t2;
DROP TABLE t2,t1,t;

harrypask, can you confirm that this is an issue with your scripts and not a MariaDB Server bug?

Generated at Thu Feb 08 10:29:20 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.