--echo # --echo # MDEV-40107 --echo # Test whether mariadb-backup/mbstream handles sparse PAGE_COMPRESSED .ibd files efficiently --echo # --source include/have_innodb.inc --source include/not_embedded.inc --disable_warnings DROP DATABASE IF EXISTS pc_sparse_test; --enable_warnings CREATE DATABASE pc_sparse_test; USE pc_sparse_test; --echo # --echo # Create comparable uncompressed and PAGE_COMPRESSED tables --echo # CREATE TABLE t_uncompressed ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 VARCHAR(100), pad VARCHAR(2000) ) ENGINE=InnoDB; CREATE TABLE t_page_compressed ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, c1 VARCHAR(100), pad VARCHAR(2000) ) ENGINE=InnoDB PAGE_COMPRESSED=1; --echo # --echo # Insert compressible data --echo # DELIMITER |; CREATE PROCEDURE load_data() BEGIN DECLARE i INT DEFAULT 0; WHILE i < 30000 DO INSERT INTO t_uncompressed(c1, pad) VALUES (CONCAT('row-', i), REPEAT('A', 2000)); INSERT INTO t_page_compressed(c1, pad) VALUES (CONCAT('row-', i), REPEAT('A', 2000)); SET i = i + 1; END WHILE; END| DELIMITER ;| CALL load_data(); DROP PROCEDURE load_data; FLUSH TABLES; --echo # --echo # Confirm table row counts --echo # SELECT COUNT(*) FROM t_uncompressed; SELECT COUNT(*) FROM t_page_compressed; --echo # --echo # Check source .ibd sparse status --echo # --perl use strict; use warnings; my $datadir = "$ENV{MYSQLTEST_VARDIR}/mysqld.1/data"; my $dbdir = "$datadir/pc_sparse_test"; my $u = "$dbdir/t_uncompressed.ibd"; my $p = "$dbdir/t_page_compressed.ibd"; sub stat_file { my ($name, $file) = @_; my @s = stat($file) or die "Cannot stat $file: $!"; my $size = $s[7]; my $blocks = $s[12] || 0; my $allocated = $blocks * 512; my $sparse = ($allocated > 0 && $allocated < $size) ? "YES" : "NO"; my $apparent_gt_allocated = ($size > $allocated && $allocated > 0) ? "YES" : "NO"; print "$name size_present=YES\n"; print "$name sparse=$sparse\n"; print "$name apparent_gt_allocated=$apparent_gt_allocated\n"; } stat_file("source_uncompressed", $u); stat_file("source_page_compressed", $p); EOF --echo # --echo # Prepare backup and extract directories --echo # --perl use strict; use warnings; use File::Path qw(remove_tree make_path); my $tmpdir = "$ENV{MYSQLTEST_VARDIR}/tmp"; my $backup_dir = "$tmpdir/pc_sparse_backup"; my $extract_dir = "$tmpdir/pc_sparse_extract"; my $stream_file = "$tmpdir/pc_sparse_backup.mbstream"; remove_tree($backup_dir) if -d $backup_dir; remove_tree($extract_dir) if -d $extract_dir; unlink $stream_file if -f $stream_file; make_path($backup_dir); make_path($extract_dir); EOF --echo # --echo # Run normal mariadb-backup to local target-dir --echo # --let $backup_dir=$MYSQLTEST_VARDIR/tmp/pc_sparse_backup --let $mariadb_backup=$MYSQLTEST_VARDIR/../../bin/mariadb-backup --let $mbstream=$MYSQLTEST_VARDIR/../../bin/mbstream --exec $mariadb_backup --backup --target-dir=$backup_dir --user=root --socket=$MASTER_MYSOCK > $MYSQLTEST_VARDIR/tmp/pc_sparse_backup.log 2>&1 --echo # --echo # Check backed-up .ibd sparse status --echo # --perl use strict; use warnings; my $backup_dir = "$ENV{MYSQLTEST_VARDIR}/tmp/pc_sparse_backup"; my $dbdir = "$backup_dir/pc_sparse_test"; my $u = "$dbdir/t_uncompressed.ibd"; my $p = "$dbdir/t_page_compressed.ibd"; sub stat_file { my ($name, $file) = @_; my @s = stat($file) or die "Cannot stat $file: $!"; my $size = $s[7]; my $blocks = $s[12] || 0; my $allocated = $blocks * 512; my $sparse = ($allocated > 0 && $allocated < $size) ? "YES" : "NO"; my $apparent_gt_allocated = ($size > $allocated && $allocated > 0) ? "YES" : "NO"; print "$name size_present=YES\n"; print "$name sparse=$sparse\n"; print "$name apparent_gt_allocated=$apparent_gt_allocated\n"; } stat_file("backup_uncompressed", $u); stat_file("backup_page_compressed", $p); EOF --echo # --echo # Run mariadb-backup streaming through mbstream --echo # --let $stream_file=$MYSQLTEST_VARDIR/tmp/pc_sparse_backup.mbstream --exec $mariadb_backup --backup --stream=mbstream --user=root --socket=$MASTER_MYSOCK > $stream_file 2> $MYSQLTEST_VARDIR/tmp/pc_sparse_stream.log --echo # --echo # Compare source PAGE_COMPRESSED .ibd logical size, allocated size, --echo # and generated mbstream size --echo # --perl use strict; use warnings; my $datadir = "$ENV{MYSQLTEST_VARDIR}/mysqld.1/data"; my $stream_file = "$ENV{MYSQLTEST_VARDIR}/tmp/pc_sparse_backup.mbstream"; my $pc_file = "$datadir/pc_sparse_test/t_page_compressed.ibd"; my @s_pc = stat($pc_file) or die "Cannot stat $pc_file: $!"; my @s_stream = stat($stream_file) or die "Cannot stat $stream_file: $!"; my $pc_size = $s_pc[7]; my $pc_allocated = ($s_pc[12] || 0) * 512; my $stream_size = $s_stream[7]; print "stream_file_present=YES\n"; if ($pc_allocated > 0 && $pc_size > $pc_allocated) { print "source_page_compressed_is_sparse=YES\n"; } else { print "source_page_compressed_is_sparse=NO\n"; } if ($stream_size >= $pc_size * 0.80) { print "stream_close_to_apparent_size=YES\n"; } else { print "stream_close_to_apparent_size=NO\n"; } if ($pc_allocated > 0 && $stream_size > $pc_allocated * 2) { print "stream_much_larger_than_allocated_size=YES\n"; } else { print "stream_much_larger_than_allocated_size=NO\n"; } EOF --echo # --echo # Extract mbstream and check extracted sparse status --echo # --let $extract_dir=$MYSQLTEST_VARDIR/tmp/pc_sparse_extract --exec $mbstream -x -C $extract_dir < $stream_file > $MYSQLTEST_VARDIR/tmp/pc_sparse_extract.log 2>&1 --perl use strict; use warnings; my $extract_dir = "$ENV{MYSQLTEST_VARDIR}/tmp/pc_sparse_extract"; my $dbdir = "$extract_dir/pc_sparse_test"; my $u = "$dbdir/t_uncompressed.ibd"; my $p = "$dbdir/t_page_compressed.ibd"; sub stat_file { my ($name, $file) = @_; my @s = stat($file) or die "Cannot stat $file: $!"; my $size = $s[7]; my $blocks = $s[12] || 0; my $allocated = $blocks * 512; my $sparse = ($allocated > 0 && $allocated < $size) ? "YES" : "NO"; my $apparent_gt_allocated = ($size > $allocated && $allocated > 0) ? "YES" : "NO"; print "$name size_present=YES\n"; print "$name sparse=$sparse\n"; print "$name apparent_gt_allocated=$apparent_gt_allocated\n"; } stat_file("extract_uncompressed", $u); stat_file("extract_page_compressed", $p); EOF --echo # --echo # Cleanup --echo # DROP DATABASE pc_sparse_test; --perl use strict; use warnings; use File::Path qw(remove_tree); my $tmpdir = "$ENV{MYSQLTEST_VARDIR}/tmp"; my $backup_dir = "$tmpdir/pc_sparse_backup"; my $extract_dir = "$tmpdir/pc_sparse_extract"; my $stream_file = "$tmpdir/pc_sparse_backup.mbstream"; remove_tree($backup_dir) if -d $backup_dir; remove_tree($extract_dir) if -d $extract_dir; unlink $stream_file if -f $stream_file; unlink "$tmpdir/pc_sparse_backup.log" if -f "$tmpdir/pc_sparse_backup.log"; unlink "$tmpdir/pc_sparse_stream.log" if -f "$tmpdir/pc_sparse_stream.log"; unlink "$tmpdir/pc_sparse_extract.log" if -f "$tmpdir/pc_sparse_extract.log"; EOF