polardbxengine/mysql-test/suite/rpl/t/rpl_connection_compression....

476 lines
16 KiB
Plaintext

# ==== Requirements ====
#
# R1. If the intersection of slave's MASTER_COMPRESSION_ALGORITHMS with
# master's @@global.protocol_compression_algorithms is nonempty, then
# the connection in START SLAVE shall succeed and use zlib if
# possible; otherwise zstd; otherwise uncompressed.
#
# R2. If the intersection of slave's MASTER_COMPRESSION_ALGORITHMS with
# master's @@global.protocol_compression_algorithms is empty, then
# connection shall fail with an error.
#
# R3. If slave connects with MASTER_COMPRESSION_ALGORITHMS = 'zlib' or
# 'zstd', the connection should be compressed.
#
# R4. If slave connects with MASTER_COMPRESSION_ALGORITHMS = NULL, the
# connection should be uncompressed.
#
# R5. When using the zstd algorithm, MASTER_ZSTD_COMPRESSION_LEVEL=N
# shall provide better compression ratio than M, if N > M.
#
# ==== References ====
#
# WL#12475 - Protocol Changes to specify compression configuration for
# connections
#
# Test does not depend on binlog_format, so should only run once.
--source include/have_binlog_format_row.inc
--let $rpl_skip_start_slave = 1
--source include/master-slave.inc
--echo #### Initialize ####
# Don't replicate the auxiliary tables.
SET sql_log_bin = 0;
# List of possible values for MASTER_COMPRESSION_ALGORITHMS
CREATE TABLE algorithms (
id INT AUTO_INCREMENT PRIMARY KEY,
name TEXT NOT NULL);
INSERT INTO algorithms(name) VALUES
('default'),
('zlib'),
('zstd'),
('uncompressed'),
('zlib,zstd'),
('zlib,uncompressed'),
('zstd,uncompressed'),
('zlib,zstd,uncompressed');
# The options above includes all real possibilities. The options
# below are only variants of the syntax, where algorithms appear in
# different orders. This test is a bit slow, so we skip the options
# below, to save time.
#('zstd,zlib'),
#('uncompressed,zlib'),
#('uncompressed,zstd'),
#('zlib,uncompressed,zstd'),
#('zstd,zlib,uncompressed'),
#('zstd,uncompressed,zlib'),
#('uncompressed,zlib,zstd'),
#('uncompressed,zstd,zlib');
--let $algorithm_count = `SELECT COUNT(*) FROM algorithms`
# List of tested values for MASTER_ZSTD_COMPRESSION_LEVEL
CREATE TABLE levels (
id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'order in which to set option',
level TEXT NOT NULL COMMENT 'compression level',
position INT NOT NULL COMMENT 'expected ordinal position of achieved compression'
);
# Exclude some levels, to make the test faster.
# Intermediate compression levels are not making much difference, test default and max.
INSERT INTO levels(level, position) VALUES
# ('1', 1),
#('2', 2),
('default', 3),
#('3', 3),
#('13', 4),
('22', 5);
--let $level_count = `SELECT COUNT(*) FROM levels`
--delimiter |
# Given two comma-separated lists of strings, returns a
# comma-separated list of those strings that appear in both, with
# duplicates removed, in the order of set1.
CREATE FUNCTION set_intersection(set1 TEXT, set2 TEXT) RETURNS TEXT BEGIN
DECLARE ret TEXT DEFAULT '';
DECLARE elem TEXT;
WHILE set1 != '' DO
SET elem = SUBSTRING_INDEX(set1, ',', 1);
IF FIND_IN_SET(elem, set2) THEN
SET ret = sys.list_add(ret, elem);
SET set2 = sys.list_drop(set2, elem);
END IF;
SET set1 = sys.list_drop(set1, elem);
END WHILE;
RETURN ret;
END|
--delimiter ;
SET sql_log_bin = 1;
# Statement to reset replication
--let $change_master_base = CHANGE MASTER TO MASTER_HOST = '127.0.0.1', MASTER_PORT = $SERVER_MYPORT_1, MASTER_USER = 'root', MASTER_RETRY_COUNT=3, MASTER_CONNECT_RETRY=1;
--let $script_dir = $MYSQLTEST_VARDIR
# ---- Purpose ----
#
# Auxiliary script to set configuration options on slave.
#
# ---- Usage ----
#
# --let $change_master_base = <CHANGE MASTER STATEMENT>
# --let $change_master_algorithm = <CHANGE MASTER STATEMENT>
# --let $change_master_level = <CHANGE MASTER STATEMENT>
# --let $slave_compressed_protocol = [0|1]
# --source $script_dir/configure_slave.inc
#
# Parameters:
#
# $change_master_base
# CHANGE MASTER statement that sets non-compression attributes to
# do the base configuration of the channel; for instance
# MASTER_HOST, MASTER_USER, etc.
#
# $change_master_algorithm
# CHANGE MASTER statement that sets MASTER_COMPRESSION_ALGORITHMS.
#
# $change_master_level
# CHANGE MASTER statement that sets MASTER_ZSTD_COMPRESSION_LEVEL.
#
# $slave_compressed_protocol
# Set @@global.slave_compressed_protocol to this value.
#
--write_file $script_dir/configure_slave.inc
# Make the 'source ...' files less noisy
--let $rpl_connection_silent = 1
--let $include_silent = 1
--source include/rpl_connection_slave.inc
--disable_warnings
--disable_query_log
eval $change_master_base;
--enable_query_log
if ($change_master_algorithm != '') {
eval $change_master_algorithm;
}
if ($change_master_level != '') {
eval $change_master_level;
}
--enable_warnings
eval SET @@global.slave_compressed_protocol = $slave_compressed_protocol;
EOF
# ---- Purpose ----
#
# Test one configuration that is expected to succeed, and verify
# requirements R1, R3, and R4.
#
# ---- Usage ----
#
# --let $change_master_base = <CHANGE MASTER STATEMENT>
# --let $change_master_algorithm = <CHANGE MASTER STATEMENT>
# --let $change_master_level = <CHANGE MASTER STATEMENT>
# --let $slave_compressed_protocol = [0|1]
# --let $data_size = size of data in event
# --let $expected_algorithm = [zlib|zstd|uncompressed]
# --source $script_dir/test_master_slave_compression.inc
#
# Parameters:
#
# $change_master_base, $change_master_algorithm, $change_master_level,
# $slave_compressed_protocol
# See configure_slave.inc
#
# $data_size
# The size of the data that was inserted on master.
# We will expect that it sends more than this if the connection is
# uncompressed, and less than this if the connection is compressed.
#
# $expected_algorithm
# The algorithm that should be used in the protocol.
#
# ---- Implementation ----
#
# - Configure slave using CHANGE MASTER
# - Start replication threads
# - Measure the number of bytes sent on the connection before and after
# - If the expected algorithm is uncompressed, assert that it sent
# more than $data_size bytes (data plus overhead)
# - If the expected algorithm is compressed, assert that it sent less
# than $data_size bytes (we assume that compression saves more than
# the overhead).
--write_file $script_dir/test_master_slave_compression.inc
--source $script_dir/configure_slave.inc
# Get initial value for number of bytes sent.
--source include/rpl_connection_master.inc
--source include/save_master_pos.inc
--let $bytes_before = `SELECT SUM_NUMBER_OF_BYTES_WRITE FROM performance_schema.socket_summary_by_event_name WHERE EVENT_NAME = 'wait/io/socket/sql/client_connection'`
--echo START SLAVE IO_THREAD
# Verify that slave can connect
--source include/rpl_connection_slave.inc
--source include/start_slave_io.inc
# Replicate
--source include/sync_slave_io.inc
--source include/stop_slave_io.inc
# Get final value for total number of bytes sent.
--source include/rpl_connection_master.inc
--let $bytes_after = `SELECT SUM_NUMBER_OF_BYTES_WRITE FROM performance_schema.socket_summary_by_event_name WHERE EVENT_NAME = 'wait/io/socket/sql/client_connection'`
--let $bytes_sent = `SELECT $bytes_after - $bytes_before`
# Verify that data was compressed / uncompressed according to option
if ($expected_algorithm == uncompressed) {
--let $assert_cond = $bytes_sent > $data_size
--let $assert_text = More than $data_size bytes should be sent uncompressed
}
if ($expected_algorithm != uncompressed) {
--let $assert_cond = $bytes_sent < $data_size
--let $assert_text = Less than $data_size bytes should be sent compressed
}
--let $include_silent = 0
--source include/assert.inc
--source include/rpl_connection_slave.inc
--disable_query_log
RESET MASTER;
RESET SLAVE ALL;
--enable_query_log
EOF
# ---- Purpose ----
#
# Do the same as $script_dir/test_master_slave_compression.inc, and
# in addition verify requirement R5.
#
# ---- Usage ----
#
# --let $change_master_base = <CHANGE MASTER STATEMENT>
# --let $change_master_algorithm = <CHANGE MASTER STATEMENT>
# --let $change_master_level = <CHANGE MASTER STATEMENT>
# --let $slave_compressed_protocol = [0|1]
# --let $data_size = size of data in event
# --let $expected_algorithm = [zlib|zstd|uncompressed]
# --let $level_it = NUMBER
# --source $script_dir/test_master_slave_compression_with_level
#
# Parameters:
#
# $change_master_base, $change_master_algorithm, $change_master_level,
# $slave_compressed_protocol, $data_size, $expected_algorithm
# See test_master_slave_compression.inc, above.
#
# $level_it
# Row number in the 'levels' table which contains the compression
# level to test.
#
# ---- Implementation ----
#
# - Fetch the compression level from the levels table.
# - Add MASTER_ZSTD_COMPRESSION_LEVEL to the CHANGE MASTER statement text
# - Source test_master_slave_compression
# - If level_it != 1 (it's not the first level we try for the
# algorithm), compare the compression ratio with the compression
# ratio of the last run. If the 'position' column of the 'levels'
# table has the same value as the 'position' column for the previous
# row in the 'levels' table, then we expect the compression ratios
# to be the same. Otherwise (i.e. the 'position' column is greater
# than that of the previous row), then we expect the compression
# ratio of the current test to be better than that of the last test.
--write_file $script_dir/test_master_slave_compression_with_level.inc
--source include/rpl_connection_master.inc
--source $script_dir/test_master_slave_compression.inc
--source include/rpl_connection_master.inc
# If this is not the first run with this algorithm, compare with previous
# run. If the 'position' value for this row in the 'levels' table equals
# the 'position' value for the previous row, then the levels are
# the same and we should expect equal compression. Otherwise, this level
# is higher than the previous level and we should expect the compression
# to be better than the previous run.
if ($level_it != 1) {
--let $better_than_last = `SELECT position > $last_position FROM levels WHERE id = $level_it`
if ($better_than_last) {
--let $assert_cond = $bytes_sent < $last_bytes_sent
--let $assert_text = Compression ratio should be better than previous algorithm
}
if (!$better_than_last) {
--let $assert_cond = $bytes_sent == $last_bytes_sent
--let $assert_text = Compression ratio should be equal to previous algorithm
}
--source include/assert.inc
}
--let $last_bytes_sent = $bytes_sent
--let $last_position = `SELECT position FROM levels WHERE id = $level_it`
EOF
# ---- Purpose ----
#
# Verify that there is an error when master and slave do not have any
# compression algorithm in common.
#
# ---- Usage ----
#
# --let $change_master_base = <CHANGE MASTER STATEMENT>
# --let $change_master_algorithm = <CHANGE MASTER STATEMENT>
# --source $script_dir/test_master_slave_compression_error.inc
#
# Parameters: See test_master_slave_compression.inc.
#
# ---- Implementation ----
#
# - Execute the CHANGE MASTER statement
# - Execute START SLAVE IO_THREAD
# - Wait until error happens.
--write_file $script_dir/test_master_slave_compression_error.inc
--source $script_dir/configure_slave.inc
START SLAVE IO_THREAD;
--let $slave_io_errno = 3922, 2066
# 3922 = ER_WRONG_COMPRESSION_ALGORITHM_CLIENT
# 2066 = CR_COMPRESSION_WRONGLY_CONFIGURED
--source include/wait_for_slave_io_error.inc
--echo got error
RESET SLAVE ALL;
EOF
# Generate some binlog data. This will be more than 10000 bytes
# uncompressed, and less than 10000 bytes compressed.
--let $data_size = 10000
CREATE TABLE t (a LONGTEXT);
eval INSERT INTO t VALUES (REPEAT('a', $data_size));
--let $saved_protocol_compression_algorithms = `SELECT @@global.protocol_compression_algorithms`
--echo #### Test ####
# Iterate over all the algorithms on master
--let $master_algorithm_it = 1
while ($master_algorithm_it <= $algorithm_count) {
--source include/rpl_connection_master.inc
--let $master_algorithm_text = `SELECT name FROM algorithms WHERE id = $master_algorithm_it`
--let $master_algorithm = $master_algorithm_text
if ($master_algorithm == default) {
--let $master_algorithm = zlib,zstd,uncompressed
}
--echo ==== master:$master_algorithm_text ====
--source include/rpl_connection_master.inc
if ($master_algorithm_text == default) {
eval SET @@global.protocol_compression_algorithms = DEFAULT;
}
if ($master_algorithm != default) {
eval SET @@global.protocol_compression_algorithms = '$master_algorithm';
}
SELECT @@global.protocol_compression_algorithms;
# Iterate over all algorithms on slave
--let $slave_algorithm_it = 1
while ($slave_algorithm_it <= $algorithm_count) {
--source include/rpl_connection_master.inc
--let $slave_algorithm_text = `SELECT name FROM algorithms WHERE id = $slave_algorithm_it`
--let $slave_algorithm = $slave_algorithm_text
--let $change_master_algorithm = CHANGE MASTER TO MASTER_COMPRESSION_ALGORITHMS = '$slave_algorithm'
if ($slave_algorithm == default) {
--let $slave_algorithm = uncompressed
--let $change_master_algorithm =
}
--let $slave_compressed_protocol = 0
--let $slave_compressed_protocol_iterations = 1
if ($slave_algorithm == uncompressed) {
--let $slave_compressed_protocol_iterations = 2
}
while ($slave_compressed_protocol < $slave_compressed_protocol_iterations) {
--source include/rpl_connection_slave.inc
if ($slave_compressed_protocol) {
--let $slave_algorithm = zlib
}
--source include/rpl_connection_master.inc
--let $intersection = `SELECT set_intersection('$master_algorithm', '$slave_algorithm')`
if ($intersection != '') {
let $expected_algorithm = `
SELECT IF(FIND_IN_SET('zlib', '$intersection'), 'zlib',
IF(FIND_IN_SET('zstd', '$intersection'), 'zstd',
'uncompressed'))`;
if ($expected_algorithm == zstd) {
# Iterate over levels.
--let $level_it = 1
while ($level_it <= $level_count) {
# Get the compression level from the table.
--let $level = `SELECT level FROM levels WHERE id = $level_it`
# If $level != 'default', set MASTER_ZSTD_COMPRESSION_LEVEL.
# Otherwise don't.
--let $change_master_level =
if ($level != 'default') {
--let $change_master_level = CHANGE MASTER TO MASTER_ZSTD_COMPRESSION_LEVEL = $level
}
--echo ---- master:$master_algorithm slave:$slave_algorithm slave_option:$slave_compressed_protocol expect:$expected_algorithm level:$level ----
--source $script_dir/test_master_slave_compression_with_level.inc
--inc $level_it
}
}
if ($expected_algorithm != zstd) {
--echo ---- master:$master_algorithm slave:$slave_algorithm_text slave_option:$slave_compressed_protocol expected:$expected_algorithm ----
--source $script_dir/test_master_slave_compression.inc
}
}
if ($intersection == '') {
--echo ---- master:$master_algorithm slave:$slave_algorithm_text slave_option:$slave_compressed_protocol expect:error ----
--source $script_dir/test_master_slave_compression_error.inc
}
--inc $slave_compressed_protocol
}
--inc $slave_algorithm_it
}
--inc $master_algorithm_it
}
--echo #### Clean up ####
--source include/rpl_connection_master.inc
--eval SET @@global.protocol_compression_algorithms = "$saved_protocol_compression_algorithms";
SET sql_log_bin = 0;
DROP TABLE algorithms;
DROP TABLE levels;
DROP TABLE t;
DROP FUNCTION set_intersection;
SET sql_log_bin = 1;
--remove_file $script_dir/configure_slave.inc
--remove_file $script_dir/test_master_slave_compression.inc
--remove_file $script_dir/test_master_slave_compression_with_level.inc
--remove_file $script_dir/test_master_slave_compression_error.inc
--source include/rpl_connection_slave.inc
--disable_query_log
eval CHANGE MASTER TO MASTER_HOST = '127.0.0.1', MASTER_PORT = $SERVER_MYPORT_1, MASTER_USER = 'root';
--enable_query_log
# Tell rpl_end to not try to sync
--let $rpl_skip_sync = 1
--source include/rpl_end.inc