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 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
|
# ==== Purpose ====
#
# Auxiliary test file included by 'binlog_gtid_next_xa.inc'.
# It differs from 'gtid_next_xa.test' to require to specify mandatory
# prepare or commit simulated error actions.
# Also it provides an optional server restart so the error action
# will unfold after the restart.
#
# This executes an XA PREPARE transaction, followed by an XA COMMIT or
# XA ROLLBACK transaction. It sets specified values of GTID_NEXT
# before each of the two transactions. After each transaction it
# verifies that GTID ownership is as expected.
#
# ==== Usage ====
#
# --let $gtid1= [<GTID> | ANONYMOUS | AUTOMATIC]
# --let $gtid2= [<GTID> | ANONYMOUS | AUTOMATIC | none]
# --let $commit= [COMMIT | ROLLBACK]
# --let $error_simul = ["at_prepare" | "at_commit"]
# --let $do_shutdown_after_prepare = [0 | 1]
# --let $one_phase = [one phase]
# --source extra/binlog/gtid_next_xa_error_simul.test
#
# Parameters:
#
# $commit
# If this is COMMIT, the second transaction will be an XA COMMIT
# transaction. If this is ROLLBACK, the second transaction will be
# an XA ROLLBACK transaction.
#
# $gtid1
# The value to use for GTID_NEXT for the first transaction
# (XA PREPARE).
#
# $gtid2
# The value to use for GTID_NEXT for the second transaction
# (XA COMMIT/ROLLBACK). If this is 'none', no SET GTID_NEXT
# statement is used and the previous value is reused.
#
# $one_phase
# Option to commit XA in one phase
#
# $error_simul
# This is an error in applying the prepare or the commit.
# The script accepts one of 'at_prepare' or 'at_commit' values.
# The caller must reset $error_simul=0 after the current invokation.
#
# Local vars:
#
# Error code's precise value is computed when $error_simul is set 'at_prepare'
--let $errno_at_prepare = 0
--let $errno_at_commit = 0
# Status of --log-bin of the server
--let $log_bin=`SELECT @@GLOBAL.log_bin`
# A copy of the main session var value, the var is used by $error_simul
--let $save_innodb_lock_wait_timeout = @@SESSION.innodb_lock_wait_timeout
SET @@SESSION.innodb_lock_wait_timeout = 1;
--echo ---- XID $xid, $commit: $gtid1 + $gtid2 ----
--source include/rpl_connection_master.inc
if ($error_simul != "at_prepare")
{
if ($error_simul != "at_commit")
{
--echo Incorrect 'error_simul' parameter value of $error_simul.
--die
}
}
if ($gtid1 != none)
{
if (!$one_phase)
{
eval SET GTID_NEXT= '$gtid1';
}
if ($one_phase)
{
# In the One-phase commit case the commit gtid2 is only used in the test
eval SET GTID_NEXT= '$gtid2';
}
}
# Prepare error pre-simulation block is place here, before even XA START
# to satisfy both the log-bin OFF and ON case. In the latter one SET @@debug
# cannot be done after XA END.
# ONE PHASE option skips the pre- and the post- prepare error simulation
# handling.
if (!$one_phase)
{
if ($error_simul == "at_prepare")
{
if (!$log_bin)
{
--connection conn_err_simul
BEGIN;
--eval INSERT INTO mysql.gtid_executed VALUES ('$uuida',$xid,$xid)
--source include/rpl_connection_master.inc
--disable_query_log
SET @@SESSION.debug = "+d,disable_se_persists_gtid";
--enable_query_log
# The "head" reported error won't be ER_XA_RBROLLBACK
--let $errno_at_prepare=ER_LOCK_WAIT_TIMEOUT
}
if ($log_bin)
{
--let $errno_at_prepare=ER_XA_RBROLLBACK
SET @@SESSION.debug = "+d,simulate_xa_failure_prepare";
}
}
}
eval XA START '$xid';
eval INSERT INTO t1 VALUES($xid);
eval XA END '$xid';
if (!$one_phase)
{
--error $errno_at_prepare
eval XA PREPARE '$xid';
# Prepare error post-simulation block
if ($error_simul == "at_prepare")
{
if (!$log_bin)
{
--connection conn_err_simul
ROLLBACK;
--echo *** The failed at XA PREPARE trx is rolled back, so XA RECOVER ***
--echo *** results in empty list: ***
XA RECOVER;
}
--source include/rpl_connection_master.inc
# Display XA specific error among other reported ones incl the "head" one
SHOW WARNINGS;
# Prepare simulation error indudes the following error at commit
--let $errno_at_commit= ER_XAER_NOTA
if ($log_bin)
{
SET @@SESSION.debug = "-d,simulate_xa_failure_prepare";
}
if (!$log_bin)
{
--disable_query_log
SET @@SESSION.debug = "-d,disable_se_persists_gtid";
--enable_query_log
}
#
# Prove that the simulated error in saving GTID does not update
# neither 'mysql.gtid_executed' table nor @@global.gtid_executed.
#
if (`SELECT GTID_SUBSET('$uuida:$xid', @@GLOBAL.gtid_executed)`)
{
--echo Unexpected committed gtid item $uuida:$xid in @@global.gtid_executed
--die
}
if (`SELECT count(*) > 0 FROM mysql.gtid_executed WHERE source_uuid = '$uuida' AND interval_start = $xid AND interval_end = $xid`)
{
--echo Unexpected committed gtid record $uuida:$xid in 'mysql.gtid_executed'
--die
}
}
--let $assert_text= Thread should not own any GTID.
--let $assert_cond= @@SESSION.GTID_OWNED = ""
--source include/assert.inc
--source include/rpl_connection_master1.inc
--let $assert_text= No thread should own any GTID.
--let $assert_cond= @@GLOBAL.GTID_OWNED = ""
--source include/assert.inc
--let $assert_text= No thread should hold anonymous ownership.
--let $assert_cond= [SHOW STATUS LIKE "ONGOING_ANONYMOUS_TRANSACTION_COUNT", Value, 1] = 0
--source include/assert.inc
if ($do_shutdown_after_prepare)
{
if (!$log_bin)
{
--disconnect conn_err_simul
}
--let $rpl_server_number= 1
--source include/rpl_restart_server.inc
--source include/rpl_set_gtid_mode.inc
if (!$log_bin)
{
--connect(conn_err_simul,localhost,root,,)
}
--source include/rpl_connection_master.inc
SET @@SESSION.innodb_lock_wait_timeout = 1;
# Prove that the prepared XA did not enroll 'mysql.gtid_executed', so
# its gtid record has been already committed:
--eval SELECT count(*) as one FROM mysql.gtid_executed WHERE source_uuid = '$uuida' AND interval_end = $xid
# No rows of the table is being locked by any other (XA) transaction
SELECT sum(interval_end+1)-sum(interval_start) as "count" FROM mysql.gtid_executed FOR UPDATE;
}
--source include/rpl_connection_master.inc
--echo error=$error_commit
if ($gtid2 != none)
{
eval SET GTID_NEXT= '$gtid2';
}
}
if ($commit == ROLLBACK)
{
# Reset $one_phase to empty in this case to satisfy syntax
--let $one_phase=
}
# Commit error pre-simulation block
if ($error_simul == "at_commit")
{
if (!$log_bin)
{
# simulate prepare error
--connection conn_err_simul
BEGIN;
--eval INSERT INTO mysql.gtid_executed VALUES ('$uuidb',$xid,$xid)
--source include/rpl_connection_master.inc
--disable_query_log
SET @@SESSION.debug = "+d,disable_se_persists_gtid";
--enable_query_log
# The "head" reported error won't be ER_XA_RBROLLBACK
--let $errno_at_commit=ER_LOCK_WAIT_TIMEOUT
}
if ($log_bin)
{
SET @@SESSION.debug = "+d,simulate_xa_rm_error";
--let $errno_at_commit=ER_XA_RBROLLBACK
}
}
--error $errno_at_commit
eval XA $commit '$xid' $one_phase;
# Prepare error post-simulation block
if ($error_simul == "at_commit")
{
if (!$log_bin)
{
--connection conn_err_simul
ROLLBACK;
--echo *** The failed at XA COMMIT trx is rolled back, so XA RECOVER ***
--echo *** results in empty list: ***
XA RECOVER;
--source include/rpl_connection_master.inc
# Display XA specific error among other reported ones incl the "head" one
SHOW WARNINGS;
--disable_query_log
SET @@SESSION.debug = "-d,disable_se_persists_gtid";
--enable_query_log
#
# Prove that the simulated error in saving GTID does not update
# neither 'mysql.gtid_executed' table nor @@global.gtid_executed.
#
if (`SELECT GTID_SUBSET('$uuidb:$xid', @@GLOBAL.gtid_executed)`)
{
--echo Unexpected committed gtid item $uuidb:$xid in @@global.gtid_executed
--die
}
if (`SELECT count(*) > 0 FROM mysql.gtid_executed WHERE source_uuid = '$uuidb' AND interval_start = $xid AND interval_end = $xid`)
{
--echo Unexpected committed gtid record $uuidb:$xid in 'mysql.gtid_executed'
--die
}
}
if ($log_bin)
{
SET @@SESSION.debug = "-d,simulate_xa_rm_error";
}
}
--let $assert_text= Thread should not own any GTID.
--let $assert_cond= @@SESSION.GTID_OWNED = ""
--source include/assert.inc
--let $assert_text= No thread should own any GTID.
--let $assert_cond= @@GLOBAL.GTID_OWNED = ""
--source include/assert.inc
--let $assert_text= No thread should hold anonymous ownership.
--let $assert_cond= [SHOW STATUS LIKE "ONGOING_ANONYMOUS_TRANSACTION_COUNT", Value, 1] = 0
--source include/assert.inc
ROLLBACK;
# Restore orig wait timeout
--eval SET @@SESSION.innodb_lock_wait_timeout = $save_innodb_lock_wait_timeout
--inc $xid
SET GTID_NEXT = 'AUTOMATIC';
|