
Added a test that makes sure the transaction replay cap is respected. Also improved the logging to show how many transaction replay attemps have been done and to log if a replay is not done due to too many attempts.
84 lines
2.4 KiB
C++
84 lines
2.4 KiB
C++
/**
|
|
* MXS-2456: Cap transaction replay attempts
|
|
* https://jira.mariadb.org/browse/MXS-2456
|
|
*/
|
|
|
|
#include "testconnections.h"
|
|
|
|
#define EXPECT(a) test.expect(a, "%s", "Assertion failed: " #a)
|
|
|
|
void test_replay_ok(TestConnections& test)
|
|
{
|
|
Connection c = test.maxscales->rwsplit();
|
|
EXPECT(c.connect());
|
|
EXPECT(c.query("BEGIN"));
|
|
EXPECT(c.query("SELECT 1"));
|
|
EXPECT(c.query("SELECT SLEEP(15)"));
|
|
|
|
// Block the node where the transaction was started
|
|
test.repl->block_node(0);
|
|
test.maxscales->wait_for_monitor();
|
|
sleep(5);
|
|
|
|
// Then block the node where the transaction replay is attempted before the last statement finishes
|
|
test.repl->block_node(1);
|
|
test.maxscales->wait_for_monitor();
|
|
sleep(5);
|
|
|
|
// The next query should succeed as we do two replay attempts
|
|
test.expect(c.query("SELECT 2"), "Two transaction replays should work");
|
|
|
|
// Reset the replication
|
|
test.repl->unblock_node(1);
|
|
test.repl->unblock_node(0);
|
|
test.maxscales->wait_for_monitor();
|
|
test.check_maxctrl("call command mariadbmon reset-replication MariaDB-Monitor server1");
|
|
test.maxscales->wait_for_monitor();
|
|
}
|
|
|
|
void test_replay_failure(TestConnections& test)
|
|
{
|
|
Connection c = test.maxscales->rwsplit();
|
|
c.connect();
|
|
c.query("BEGIN");
|
|
c.query("SELECT 1");
|
|
c.query("SELECT SLEEP(15)");
|
|
|
|
// Block the node where the transaction was started
|
|
test.repl->block_node(0);
|
|
test.maxscales->wait_for_monitor();
|
|
sleep(5);
|
|
|
|
// Then block the node where the first transaction replay is attempted
|
|
test.repl->block_node(1);
|
|
test.maxscales->wait_for_monitor();
|
|
sleep(5);
|
|
|
|
// Block the final node before the replay completes
|
|
test.repl->block_node(2);
|
|
test.maxscales->wait_for_monitor();
|
|
sleep(5);
|
|
|
|
// The next query should fail as we exceeded the cap of two replays
|
|
test.expect(!c.query("SELECT 2"), "Three transaction replays should NOT work");
|
|
|
|
// Reset the replication
|
|
test.repl->unblock_node(2);
|
|
test.repl->unblock_node(1);
|
|
test.repl->unblock_node(0);
|
|
test.maxscales->wait_for_monitor();
|
|
test.check_maxctrl("call command mariadbmon reset-replication MariaDB-Monitor server1");
|
|
test.maxscales->wait_for_monitor();
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
Mariadb_nodes::require_gtid(true);
|
|
TestConnections test(argc, argv);
|
|
|
|
test_replay_ok(test);
|
|
test_replay_failure(test);
|
|
|
|
return test.global_result;
|
|
}
|