1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
# ==== Purpose ====
#
# Check that slave handles an applier error according to
# replica_exec_mode, slave_skip_error, or none of them.
#
# ==== Usage ====
#
# --let $desc= TEXT
# [--let $first_case= N]
# --let $table= DB.TABLE
# --let $column_def= DEFINITION
# [--let $column_def_slave= DEFINITION]
# --let $rows= (comma-separated-values) [, (comma-separated-values) ...]
# [--let $rows_slave= (comma-separated-values) [, (comma-separated-values) ...]]
# [--let $insert_columns= (col1, col2, ...)]
# --let $stmt_pre= PREFIX
# --let $stmt= STMT
# --let $stmt_post= SUFFIX
# [--let $master_debug_symbol= SYMBOL]
# [--let $slave_debug_symbol= SYMBOL]
# --let $error= NUMBER
# --let $error_mode= { FAIL | SKIP | IDEMPOTENT }
# --source include/rpl_handle_applier_error.inc
#
# Invariants:
# - Replication threads should be running, and will be left running.
# - replica_exec_mode or slave_skip_error should be set according to $error_mode.
#
# Parameters:
#
# $desc
# Human-readable description of the scenario
#
# $first_case
# If set, will skip the first $first_case invocations of this script.
# (For debugging.)
#
# $table
# Fully qualified name of table to operate on
#
# $column_def
# Column definitions for table, i.e., everything between opening
# parenthesis and closing parenthesis in CREATE TABLE (...).
#
# $column_def_slave
# Different column definition for slave. If this is not set, slave
# will use the same column definition as the master.
#
# $rows
# Row values to insert in the table.
#
# $rows_slave
# Different rows to insert in the slave's table. If this is not set,
# slave will use the same values as master.
#
# $insert_columns
# Comma-separated, parenthesis-wrapped list of names of columns to
# insert, used as in
# INSERT INTO table (col1, col2, ...) VALUES ...
#
# $stmt_pre, $stmt, $stmt_post
# These strings will be concatenated, and the result executed as an
# SQL statement on the master and replicated to slave. The
# assumption is that it will generate an error in the applier
# thread on the slave.
#
# $master_debug_symbol
# If set, this debug symbol will be added to @@global.debug on
# master, before executing the statement on master.
#
# $slave_debug_symbol
# If set, this debug symbol will be added to @@global.debug on
# slave, before executing the statement on master.
#
# $error
# Expected error code (numeric).
#
# $error_mode
# How error will be handled. FAIL means the default mode where the
# threads stop with an error. SKIP means slave_skip_error is set
# to the error and the slave is expected to continue. IDEMPOTENT
# means the slave is expected to skip duplicate-key and
# key-not-found errors.
#
# $recover_from_error
# By default, does not attempt to recover from the error. If this
# variable is set, assumes the error is due to a difference between
# master and slave, and re-creates the table on slave as a copy of
# that on the master, and then tries again.
if (!$case) {
--let $case= 0
}
--inc $case
--let $skip_case= 0
if ($first_case) {
if ($case < $first_case) {
--let $skip_case= 1
}
}
if ($last_case) {
if ($case > $last_case) {
--let $skip_case= 1
}
}
--echo ==== $case. $desc ====
--let $include_filename= rpl_row_jsondiff_error_scenario [$error/$error_mode]
--source include/begin_include_file.inc
if (!$skip_case)
{
#--disable_query_log
--source include/rpl_connection_slave.inc
--let $actual_error_mode= $error_mode
if ($error_mode == IDEMPOTENT)
{
--let $actual_error_mode= FAIL
if ($error == $er_dup_entry) {
--let $actual_error_mode= SKIP
}
if ($error == $er_key_not_found) {
--let $actual_error_mode= SKIP
}
}
# Setup table on master
--source include/rpl_connection_master.inc
SET SQL_LOG_BIN = 0;
eval CREATE TABLE $table ($column_def);
eval INSERT INTO $table $insert_columns VALUES $rows;
SET SQL_LOG_BIN = 1;
# Setup table on slave
--source include/rpl_connection_slave.inc
--let $_column_def= $column_def
if ($column_def_slave) {
--let $_column_def= $column_def_slave
}
--let $_rows= $rows
if ($rows_slave) {
--let $_rows= $rows_slave
}
SET SQL_LOG_BIN = 0;
eval CREATE TABLE $table ($_column_def);
eval INSERT INTO $table $insert_columns VALUES $_rows;
SET SQL_LOG_BIN = 1;
if ($slave_debug_symbol) {
--let $debug_point= $slave_debug_symbol
--let $debug_type= GLOBAL
--source include/add_debug_point.inc
--source include/stop_slave.inc
--source include/start_slave.inc
}
# Execute statement on master
--source include/rpl_connection_master.inc
if ($master_debug_symbol) {
--let $debug_point= $master_debug_symbol
--let $debug_type= SESSION
--source include/add_debug_point.inc
}
if ($use_mysqlbinlog) {
--source include/save_binlog_position.inc
}
--eval $stmt_pre $stmt $stmt_post
if ($master_debug_symbol) {
--let $debug_point= $master_debug_symbol
--let $debug_type= SESSION
--source include/remove_debug_point.inc
}
# Verify error and cleanup error
if ($actual_error_mode == FAIL)
{
--source include/rpl_connection_slave.inc
--let $slave_sql_errno= $error
--source include/wait_for_slave_sql_error.inc
if ($use_mysqlbinlog) {
--let $mysqlbinlog_only_decoded_rows= 1
--source include/mysqlbinlog.inc
}
if ($slave_debug_symbol) {
--let $debug_point= $slave_debug_symbol
--let $debug_type= GLOBAL
--source include/remove_debug_point.inc
}
if ($recover_from_error)
{
# Create table like on master
SET SQL_LOG_BIN = 0;
eval DROP TABLE $table;
eval CREATE TABLE $table ($column_def);
eval INSERT INTO $table $insert_columns VALUES $rows;
SET SQL_LOG_BIN = 1;
# Restart replication
--source include/stop_slave_io.inc
RESET SLAVE;
--source include/start_slave.inc
--source include/rpl_connection_master.inc
# Verify no error
--source include/sync_slave_sql_with_master.inc
}
if (!$recover_from_error)
{
--source include/stop_slave_io.inc
RESET SLAVE;
--source include/rpl_connection_master.inc
RESET MASTER;
--source include/rpl_connection_slave.inc
--source include/start_slave.inc
}
}
if ($actual_error_mode == SKIP)
{
# Verify no error
--source include/sync_slave_sql_with_master.inc
if ($slave_debug_symbol) {
--let $debug_point= $slave_debug_symbol
--let $debug_type= GLOBAL
--source include/remove_debug_point.inc
}
}
# Clean up
--source include/rpl_connection_master.inc
eval DROP TABLE $table;
--source include/sync_slave_sql_with_master.inc
--source include/stop_slave.inc
# BUG#27636289: RPL BREAKS WITH RESTART AFTER RESET SLAVE,
# RESET MASTER WITH WRONG ERROR IN MTS
# Due to the above mentioned bug we need to use RESET SLAVE ALL
# and CHANGE MASTER instead of just RESET SLAVE, in order to clear
# RECEIVED_GTID_SET when test runs in MTS mode.
RESET SLAVE ALL;
RESET MASTER;
--source include/rpl_connection_master.inc
RESET MASTER;
--source include/rpl_connection_slave.inc
--replace_result $MASTER_MYPORT MASTER_PORT
--disable_warnings
eval CHANGE REPLICATION SOURCE TO SOURCE_USER='root',SOURCE_PORT=$MASTER_MYPORT,SOURCE_HOST='127.0.0.1';
--enable_warnings
--source include/start_slave.inc
}
--let $debug_point=
--source include/end_include_file.inc
|