MXS-1703 Move more functions to MariaDBServer
Also, the QueryResult integer reading method now only reads non-negative integers since the server rarely returns negative values. This frees negative values for indicating parsing error(s). Gtid-class was moved back to utility.hh/.cc because the QueryResult-class requires it.
This commit is contained in:
@ -17,7 +17,6 @@
|
|||||||
#include "utilities.hh"
|
#include "utilities.hh"
|
||||||
|
|
||||||
static int add_slave_to_master(long *slaves_list, int list_size, long node_id);
|
static int add_slave_to_master(long *slaves_list, int list_size, long node_id);
|
||||||
static void read_server_variables(MariaDBServer* serv_info);
|
|
||||||
|
|
||||||
static bool report_version_err = true;
|
static bool report_version_err = true;
|
||||||
|
|
||||||
@ -655,11 +654,11 @@ void MariaDBMonitor::monitor_database(MariaDBServer* serv_info)
|
|||||||
serv_info->version = MYSQL_SERVER_VERSION_51;
|
serv_info->version = MYSQL_SERVER_VERSION_51;
|
||||||
}
|
}
|
||||||
/* Query a few settings. */
|
/* Query a few settings. */
|
||||||
read_server_variables(serv_info);
|
serv_info->read_server_variables();
|
||||||
/* If gtid domain exists and server is 10.0, update gtid:s */
|
/* If gtid domain exists and server is 10.0, update gtid:s */
|
||||||
if (m_master_gtid_domain >= 0 && serv_info->version == MYSQL_SERVER_VERSION_100)
|
if (m_master_gtid_domain >= 0 && serv_info->version == MYSQL_SERVER_VERSION_100)
|
||||||
{
|
{
|
||||||
update_gtids(serv_info);
|
serv_info->update_gtids(m_master_gtid_domain);
|
||||||
}
|
}
|
||||||
/* Check for MariaDB 10.x.x and get status for multi-master replication */
|
/* Check for MariaDB 10.x.x and get status for multi-master replication */
|
||||||
if (serv_info->version == MYSQL_SERVER_VERSION_100 || serv_info->version == MYSQL_SERVER_VERSION_55)
|
if (serv_info->version == MYSQL_SERVER_VERSION_100 || serv_info->version == MYSQL_SERVER_VERSION_55)
|
||||||
@ -682,45 +681,6 @@ void MariaDBMonitor::monitor_database(MariaDBServer* serv_info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Read server_id, read_only and (if 10.X) gtid_domain_id. TODO: Move to MariaDBServer
|
|
||||||
*
|
|
||||||
* @param serv_info Where to save results
|
|
||||||
*/
|
|
||||||
static void read_server_variables(MariaDBServer* serv_info)
|
|
||||||
{
|
|
||||||
MXS_MONITORED_SERVER* database = serv_info->server_base;
|
|
||||||
string query = "SELECT @@global.server_id, @@read_only;";
|
|
||||||
int columns = 2;
|
|
||||||
if (serv_info->version == MYSQL_SERVER_VERSION_100)
|
|
||||||
{
|
|
||||||
query.erase(query.end() - 1);
|
|
||||||
query += ", @@global.gtid_domain_id;";
|
|
||||||
columns = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ind_id = 0;
|
|
||||||
int ind_ro = 1;
|
|
||||||
int ind_domain = 2;
|
|
||||||
StringVector row;
|
|
||||||
if (query_one_row(database, query.c_str(), columns, &row))
|
|
||||||
{
|
|
||||||
int64_t server_id = scan_server_id(row[ind_id].c_str());
|
|
||||||
database->server->node_id = server_id;
|
|
||||||
serv_info->server_id = server_id;
|
|
||||||
|
|
||||||
ss_dassert(row[ind_ro] == "0" || row[ind_ro] == "1");
|
|
||||||
serv_info->read_only = (row[ind_ro] == "1");
|
|
||||||
if (columns == 3)
|
|
||||||
{
|
|
||||||
uint32_t domain = 0;
|
|
||||||
ss_debug(int rv = ) sscanf(row[ind_domain].c_str(), "%" PRIu32, &domain);
|
|
||||||
ss_dassert(rv == 1);
|
|
||||||
serv_info->gtid_domain_id = domain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitor a database with given server info.
|
* Monitor a database with given server info.
|
||||||
*
|
*
|
||||||
@ -747,34 +707,6 @@ void MariaDBMonitor::monitor_mysql_db(MariaDBServer* serv_info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Query gtid_current_pos and gtid_binlog_pos and save the values to the server info object.
|
|
||||||
* Only the cluster master domain is parsed.
|
|
||||||
*
|
|
||||||
* @param info Server info structure for saving result TODO: move to MariaDBServer
|
|
||||||
* @return True if successful
|
|
||||||
*/
|
|
||||||
bool MariaDBMonitor::update_gtids(MariaDBServer* info)
|
|
||||||
{
|
|
||||||
MXS_MONITORED_SERVER* database = info->server_base;
|
|
||||||
StringVector row;
|
|
||||||
const char query[] = "SELECT @@gtid_current_pos, @@gtid_binlog_pos;";
|
|
||||||
const int ind_current_pos = 0;
|
|
||||||
const int ind_binlog_pos = 1;
|
|
||||||
int64_t domain = m_master_gtid_domain;
|
|
||||||
ss_dassert(domain >= 0);
|
|
||||||
bool rval = false;
|
|
||||||
if (query_one_row(database, query, 2, &row))
|
|
||||||
{
|
|
||||||
info->gtid_current_pos = (row[ind_current_pos] != "") ?
|
|
||||||
Gtid(row[ind_current_pos].c_str(), domain) : Gtid();
|
|
||||||
info->gtid_binlog_pos = (row[ind_binlog_pos] != "") ?
|
|
||||||
Gtid(row[ind_binlog_pos].c_str(), domain) : Gtid();
|
|
||||||
rval = true;
|
|
||||||
}
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update replication settings and gtid:s of the slave server.
|
* Update replication settings and gtid:s of the slave server.
|
||||||
*
|
*
|
||||||
@ -785,31 +717,11 @@ MariaDBServer* MariaDBMonitor::update_slave_info(MXS_MONITORED_SERVER* server)
|
|||||||
{
|
{
|
||||||
MariaDBServer* info = get_server_info(server);
|
MariaDBServer* info = get_server_info(server);
|
||||||
if (info->slave_status.slave_sql_running &&
|
if (info->slave_status.slave_sql_running &&
|
||||||
update_replication_settings(server, info) &&
|
info->update_replication_settings() &&
|
||||||
update_gtids(info) &&
|
info->update_gtids(m_master_gtid_domain) &&
|
||||||
info->do_show_slave_status(m_master_gtid_domain))
|
info->do_show_slave_status(m_master_gtid_domain))
|
||||||
{
|
{
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Query a few miscellaneous replication settings.
|
|
||||||
*
|
|
||||||
* @param database The slave server to query
|
|
||||||
* @param info Where to save results
|
|
||||||
* @return True on success
|
|
||||||
*/
|
|
||||||
bool MariaDBMonitor::update_replication_settings(MXS_MONITORED_SERVER *database, MariaDBServer* info)
|
|
||||||
{
|
|
||||||
StringVector row;
|
|
||||||
bool ok = query_one_row(database, "SELECT @@gtid_strict_mode, @@log_bin, @@log_slave_updates;", 3, &row);
|
|
||||||
if (ok)
|
|
||||||
{
|
|
||||||
info->rpl_settings.gtid_strict_mode = (row[0] == "1");
|
|
||||||
info->rpl_settings.log_bin = (row[1] == "1");
|
|
||||||
info->rpl_settings.log_slave_updates = (row[2] == "1");
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
@ -156,7 +156,7 @@ bool MariaDBMonitor::manual_rejoin(SERVER* rejoin_server, json_t** output)
|
|||||||
|
|
||||||
if (server_is_rejoin_suspect(mon_server, master_info, output))
|
if (server_is_rejoin_suspect(mon_server, master_info, output))
|
||||||
{
|
{
|
||||||
if (update_gtids(master_info))
|
if (master_info->update_gtids(m_master_gtid_domain))
|
||||||
{
|
{
|
||||||
if (can_replicate_from(mon_server, server_info, master_info))
|
if (can_replicate_from(mon_server, server_info, master_info))
|
||||||
{
|
{
|
||||||
@ -433,7 +433,7 @@ bool MariaDBMonitor::get_joinable_servers(ServerVector* output)
|
|||||||
bool comm_ok = true;
|
bool comm_ok = true;
|
||||||
if (!suspects.empty())
|
if (!suspects.empty())
|
||||||
{
|
{
|
||||||
if (update_gtids(master_info))
|
if (master_info->update_gtids(m_master_gtid_domain))
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < suspects.size(); i++)
|
for (size_t i = 0; i < suspects.size(); i++)
|
||||||
{
|
{
|
||||||
@ -814,7 +814,7 @@ bool MariaDBMonitor::failover_wait_relay_log(MXS_MONITORED_SERVER* new_master, i
|
|||||||
Gtid old_gtid_io_pos = master_info->slave_status.gtid_io_pos;
|
Gtid old_gtid_io_pos = master_info->slave_status.gtid_io_pos;
|
||||||
// Update gtid:s first to make sure Gtid_IO_Pos is the more recent value.
|
// Update gtid:s first to make sure Gtid_IO_Pos is the more recent value.
|
||||||
// It doesn't matter here, but is a general rule.
|
// It doesn't matter here, but is a general rule.
|
||||||
query_ok = update_gtids(master_info) &&
|
query_ok = master_info->update_gtids(m_master_gtid_domain) &&
|
||||||
master_info->do_show_slave_status(m_master_gtid_domain);
|
master_info->do_show_slave_status(m_master_gtid_domain);
|
||||||
io_pos_stable = (old_gtid_io_pos == master_info->slave_status.gtid_io_pos);
|
io_pos_stable = (old_gtid_io_pos == master_info->slave_status.gtid_io_pos);
|
||||||
}
|
}
|
||||||
@ -903,7 +903,7 @@ bool MariaDBMonitor::switchover_demote_master(MXS_MONITORED_SERVER* current_mast
|
|||||||
if (!query_error)
|
if (!query_error)
|
||||||
{
|
{
|
||||||
query = "";
|
query = "";
|
||||||
if (update_gtids(info))
|
if (info->update_gtids(m_master_gtid_domain))
|
||||||
{
|
{
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
@ -1071,7 +1071,7 @@ bool MariaDBMonitor::wait_cluster_stabilization(MXS_MONITORED_SERVER* new_master
|
|||||||
MariaDBServer* new_master_info = get_server_info(new_master);
|
MariaDBServer* new_master_info = get_server_info(new_master);
|
||||||
|
|
||||||
if (mxs_mysql_query(new_master->con, "FLUSH TABLES;") == 0 &&
|
if (mxs_mysql_query(new_master->con, "FLUSH TABLES;") == 0 &&
|
||||||
update_gtids(new_master_info))
|
new_master_info->update_gtids(m_master_gtid_domain))
|
||||||
{
|
{
|
||||||
int query_fails = 0;
|
int query_fails = 0;
|
||||||
int repl_fails = 0;
|
int repl_fails = 0;
|
||||||
@ -1094,7 +1094,8 @@ bool MariaDBMonitor::wait_cluster_stabilization(MXS_MONITORED_SERVER* new_master
|
|||||||
{
|
{
|
||||||
MXS_MONITORED_SERVER* slave = wait_list[i];
|
MXS_MONITORED_SERVER* slave = wait_list[i];
|
||||||
MariaDBServer* slave_info = get_server_info(slave);
|
MariaDBServer* slave_info = get_server_info(slave);
|
||||||
if (update_gtids(slave_info) && slave_info->do_show_slave_status(m_master_gtid_domain))
|
if (slave_info->update_gtids(m_master_gtid_domain) &&
|
||||||
|
slave_info->do_show_slave_status(m_master_gtid_domain))
|
||||||
{
|
{
|
||||||
if (!slave_info->slave_status.last_error.empty())
|
if (!slave_info->slave_status.last_error.empty())
|
||||||
{
|
{
|
||||||
@ -1157,7 +1158,7 @@ bool MariaDBMonitor::switchover_check_preferred_master(MXS_MONITORED_SERVER* pre
|
|||||||
ss_dassert(preferred);
|
ss_dassert(preferred);
|
||||||
bool rval = true;
|
bool rval = true;
|
||||||
MariaDBServer* preferred_info = update_slave_info(preferred);
|
MariaDBServer* preferred_info = update_slave_info(preferred);
|
||||||
if (preferred_info == NULL || !check_replication_settings(preferred, preferred_info))
|
if (preferred_info == NULL || !preferred_info->check_replication_settings())
|
||||||
{
|
{
|
||||||
PRINT_MXS_JSON_ERROR(err_out, "The requested server '%s' is not a valid promotion candidate.",
|
PRINT_MXS_JSON_ERROR(err_out, "The requested server '%s' is not a valid promotion candidate.",
|
||||||
preferred->server->unique_name);
|
preferred->server->unique_name);
|
||||||
@ -1234,14 +1235,14 @@ MXS_MONITORED_SERVER* MariaDBMonitor::select_new_master(ServerVector* slaves_out
|
|||||||
{
|
{
|
||||||
slaves_out->push_back(cand);
|
slaves_out->push_back(cand);
|
||||||
// Check that server is not in the exclusion list while still being a valid choice.
|
// Check that server is not in the exclusion list while still being a valid choice.
|
||||||
if (server_is_excluded(cand) && check_replication_settings(cand, cand_info, WARNINGS_OFF))
|
if (server_is_excluded(cand) && cand_info->check_replication_settings(WARNINGS_OFF))
|
||||||
{
|
{
|
||||||
valid_but_excluded.push_back(cand);
|
valid_but_excluded.push_back(cand);
|
||||||
const char CANNOT_SELECT[] = "Promotion candidate '%s' is excluded from new "
|
const char CANNOT_SELECT[] = "Promotion candidate '%s' is excluded from new "
|
||||||
"master selection.";
|
"master selection.";
|
||||||
MXS_INFO(CANNOT_SELECT, cand->server->unique_name);
|
MXS_INFO(CANNOT_SELECT, cand->server->unique_name);
|
||||||
}
|
}
|
||||||
else if (check_replication_settings(cand, cand_info))
|
else if (cand_info->check_replication_settings())
|
||||||
{
|
{
|
||||||
// If no new master yet, accept any valid candidate. Otherwise check.
|
// If no new master yet, accept any valid candidate. Otherwise check.
|
||||||
if (current_best == NULL || is_candidate_better(current_best_info, cand_info))
|
if (current_best == NULL || is_candidate_better(current_best_info, cand_info))
|
||||||
@ -1482,49 +1483,6 @@ bool MariaDBMonitor::failover_check(json_t** error_out)
|
|||||||
return !error && slaves > 0;
|
return !error && slaves > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if server has binary log enabled. Print warnings if gtid_strict_mode or log_slave_updates is off.
|
|
||||||
*
|
|
||||||
* @param server Server to check
|
|
||||||
* @param server_info Server info
|
|
||||||
* @param print_on Print warnings or not
|
|
||||||
* @return True if log_bin is on
|
|
||||||
*/
|
|
||||||
bool check_replication_settings(const MXS_MONITORED_SERVER* server, MariaDBServer* server_info,
|
|
||||||
print_repl_warnings_t print_warnings)
|
|
||||||
{
|
|
||||||
bool rval = true;
|
|
||||||
const char* servername = server->server->unique_name;
|
|
||||||
if (server_info->rpl_settings.log_bin == false)
|
|
||||||
{
|
|
||||||
if (print_warnings == WARNINGS_ON)
|
|
||||||
{
|
|
||||||
const char NO_BINLOG[] =
|
|
||||||
"Slave '%s' has binary log disabled and is not a valid promotion candidate.";
|
|
||||||
MXS_WARNING(NO_BINLOG, servername);
|
|
||||||
}
|
|
||||||
rval = false;
|
|
||||||
}
|
|
||||||
else if (print_warnings == WARNINGS_ON)
|
|
||||||
{
|
|
||||||
if (server_info->rpl_settings.gtid_strict_mode == false)
|
|
||||||
{
|
|
||||||
const char NO_STRICT[] =
|
|
||||||
"Slave '%s' has gtid_strict_mode disabled. Enabling this setting is recommended. "
|
|
||||||
"For more information, see https://mariadb.com/kb/en/library/gtid/#gtid_strict_mode";
|
|
||||||
MXS_WARNING(NO_STRICT, servername);
|
|
||||||
}
|
|
||||||
if (server_info->rpl_settings.log_slave_updates == false)
|
|
||||||
{
|
|
||||||
const char NO_SLAVE_UPDATES[] =
|
|
||||||
"Slave '%s' has log_slave_updates disabled. It is a valid candidate but replication "
|
|
||||||
"will break for lagging slaves if '%s' is promoted.";
|
|
||||||
MXS_WARNING(NO_SLAVE_UPDATES, servername, servername);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if slave can replicate from master. Only considers gtid:s and only detects obvious errors. The
|
* Checks if slave can replicate from master. Only considers gtid:s and only detects obvious errors. The
|
||||||
* non-detected errors will mostly be detected once the slave tries to start replicating.
|
* non-detected errors will mostly be detected once the slave tries to start replicating.
|
||||||
@ -1538,7 +1496,7 @@ bool MariaDBMonitor::can_replicate_from(MXS_MONITORED_SERVER* slave,
|
|||||||
MariaDBServer* slave_info, MariaDBServer* master_info)
|
MariaDBServer* slave_info, MariaDBServer* master_info)
|
||||||
{
|
{
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
if (update_gtids(slave_info))
|
if (slave_info->update_gtids(m_master_gtid_domain))
|
||||||
{
|
{
|
||||||
Gtid slave_gtid = slave_info->gtid_current_pos;
|
Gtid slave_gtid = slave_info->gtid_current_pos;
|
||||||
Gtid master_gtid = master_info->gtid_binlog_pos;
|
Gtid master_gtid = master_info->gtid_binlog_pos;
|
||||||
|
|||||||
@ -37,12 +37,6 @@ typedef std::tr1::unordered_map<MXS_MONITORED_SERVER*, MariaDBServer*> ServerInf
|
|||||||
// Server container, owns the server objects.
|
// Server container, owns the server objects.
|
||||||
typedef std::vector<MariaDBServer> ServerContainer; // TODO: Rename/get rid of ServerVector typedef!
|
typedef std::vector<MariaDBServer> ServerContainer; // TODO: Rename/get rid of ServerVector typedef!
|
||||||
|
|
||||||
enum print_repl_warnings_t
|
|
||||||
{
|
|
||||||
WARNINGS_ON,
|
|
||||||
WARNINGS_OFF
|
|
||||||
};
|
|
||||||
|
|
||||||
enum slave_down_setting_t
|
enum slave_down_setting_t
|
||||||
{
|
{
|
||||||
ACCEPT_DOWN,
|
ACCEPT_DOWN,
|
||||||
@ -51,8 +45,6 @@ enum slave_down_setting_t
|
|||||||
|
|
||||||
// TODO: Most of following should be class methods
|
// TODO: Most of following should be class methods
|
||||||
void print_redirect_errors(MXS_MONITORED_SERVER* first_server, const ServerVector& servers, json_t** err_out);
|
void print_redirect_errors(MXS_MONITORED_SERVER* first_server, const ServerVector& servers, json_t** err_out);
|
||||||
bool check_replication_settings(const MXS_MONITORED_SERVER* server, MariaDBServer* server_info,
|
|
||||||
print_repl_warnings_t print_warnings = WARNINGS_ON);
|
|
||||||
MXS_MONITORED_SERVER* getServerByNodeId(MXS_MONITORED_SERVER *, long);
|
MXS_MONITORED_SERVER* getServerByNodeId(MXS_MONITORED_SERVER *, long);
|
||||||
MXS_MONITORED_SERVER* getSlaveOfNodeId(MXS_MONITORED_SERVER *, long, slave_down_setting_t);
|
MXS_MONITORED_SERVER* getSlaveOfNodeId(MXS_MONITORED_SERVER *, long, slave_down_setting_t);
|
||||||
|
|
||||||
@ -217,7 +209,6 @@ private:
|
|||||||
bool server_is_excluded(const MXS_MONITORED_SERVER* server);
|
bool server_is_excluded(const MXS_MONITORED_SERVER* server);
|
||||||
bool is_candidate_better(const MariaDBServer* current_best_info, const MariaDBServer* candidate_info);
|
bool is_candidate_better(const MariaDBServer* current_best_info, const MariaDBServer* candidate_info);
|
||||||
MariaDBServer* update_slave_info(MXS_MONITORED_SERVER* server);
|
MariaDBServer* update_slave_info(MXS_MONITORED_SERVER* server);
|
||||||
bool update_replication_settings(MXS_MONITORED_SERVER *database, MariaDBServer* info);
|
|
||||||
void init_server_info();
|
void init_server_info();
|
||||||
bool slave_receiving_events();
|
bool slave_receiving_events();
|
||||||
void monitor_database(MariaDBServer* param_db);
|
void monitor_database(MariaDBServer* param_db);
|
||||||
@ -247,7 +238,6 @@ private:
|
|||||||
json_t** output);
|
json_t** output);
|
||||||
bool cluster_can_be_joined();
|
bool cluster_can_be_joined();
|
||||||
bool failover_check(json_t** error_out);
|
bool failover_check(json_t** error_out);
|
||||||
bool update_gtids(MariaDBServer* info);
|
|
||||||
void disable_setting(const char* setting);
|
void disable_setting(const char* setting);
|
||||||
bool switchover_check_new(const MXS_MONITORED_SERVER* monitored_server, json_t** error);
|
bool switchover_check_new(const MXS_MONITORED_SERVER* monitored_server, json_t** error);
|
||||||
bool switchover_check_current(const MXS_MONITORED_SERVER* suggested_curr_master,
|
bool switchover_check_current(const MXS_MONITORED_SERVER* suggested_curr_master,
|
||||||
|
|||||||
@ -18,68 +18,6 @@
|
|||||||
#include <maxscale/mysql_utils.h>
|
#include <maxscale/mysql_utils.h>
|
||||||
#include "utilities.hh"
|
#include "utilities.hh"
|
||||||
|
|
||||||
Gtid::Gtid()
|
|
||||||
: domain(0)
|
|
||||||
, server_id(SERVER_ID_UNKNOWN)
|
|
||||||
, sequence(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Gtid::Gtid(const char* str, int64_t search_domain)
|
|
||||||
: domain(0)
|
|
||||||
, server_id(SERVER_ID_UNKNOWN)
|
|
||||||
, sequence(0)
|
|
||||||
{
|
|
||||||
// Autoselect only allowed with one triplet
|
|
||||||
ss_dassert(search_domain >= 0 || strchr(str, ',') == NULL);
|
|
||||||
parse_triplet(str);
|
|
||||||
if (search_domain >= 0 && domain != search_domain)
|
|
||||||
{
|
|
||||||
// Search for the correct triplet.
|
|
||||||
bool found = false;
|
|
||||||
for (const char* next_triplet = strchr(str, ',');
|
|
||||||
next_triplet != NULL && !found;
|
|
||||||
next_triplet = strchr(next_triplet, ','))
|
|
||||||
{
|
|
||||||
parse_triplet(++next_triplet);
|
|
||||||
if (domain == search_domain)
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ss_dassert(found);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Gtid::operator == (const Gtid& rhs) const
|
|
||||||
{
|
|
||||||
return domain == rhs.domain &&
|
|
||||||
server_id != SERVER_ID_UNKNOWN && server_id == rhs.server_id &&
|
|
||||||
sequence == rhs.sequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
string Gtid::to_string() const
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
if (server_id != SERVER_ID_UNKNOWN)
|
|
||||||
{
|
|
||||||
ss << domain << "-" << server_id << "-" << sequence;
|
|
||||||
}
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gtid::parse_triplet(const char* str)
|
|
||||||
{
|
|
||||||
ss_debug(int rv = ) sscanf(str, "%" PRIu32 "-%" PRId64 "-%" PRIu64, &domain, &server_id, &sequence);
|
|
||||||
ss_dassert(rv == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
string Gtid::generate_master_gtid_wait_cmd(double timeout) const
|
|
||||||
{
|
|
||||||
std::stringstream query_ss;
|
|
||||||
query_ss << "SELECT MASTER_GTID_WAIT(\"" << to_string() << "\", " << timeout << ");";
|
|
||||||
return query_ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
SlaveStatusInfo::SlaveStatusInfo()
|
SlaveStatusInfo::SlaveStatusInfo()
|
||||||
: master_server_id(SERVER_ID_UNKNOWN)
|
: master_server_id(SERVER_ID_UNKNOWN)
|
||||||
, master_port(0)
|
, master_port(0)
|
||||||
@ -214,7 +152,7 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
|
|||||||
{
|
{
|
||||||
/** Only check binlog name for the first running slave */
|
/** Only check binlog name for the first running slave */
|
||||||
string master_log_file = result->get_string(i_master_log_file);
|
string master_log_file = result->get_string(i_master_log_file);
|
||||||
uint64_t read_master_log_pos = result->get_int(i_read_master_log_pos);
|
uint64_t read_master_log_pos = result->get_uint(i_read_master_log_pos);
|
||||||
if (slave_status.master_log_file != master_log_file ||
|
if (slave_status.master_log_file != master_log_file ||
|
||||||
slave_status.read_master_log_pos != read_master_log_pos)
|
slave_status.read_master_log_pos != read_master_log_pos)
|
||||||
{
|
{
|
||||||
@ -233,7 +171,7 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
|
|||||||
* root master server.
|
* root master server.
|
||||||
* Please note, there could be no slaves at all if Slave_SQL_Running == 'No'
|
* Please note, there could be no slaves at all if Slave_SQL_Running == 'No'
|
||||||
*/
|
*/
|
||||||
int64_t last_io_errno = result->get_int(i_last_io_errno);
|
int64_t last_io_errno = result->get_uint(i_last_io_errno);
|
||||||
int io_errno = last_io_errno;
|
int io_errno = last_io_errno;
|
||||||
const int connection_errno = 2003;
|
const int connection_errno = 2003;
|
||||||
|
|
||||||
@ -247,18 +185,18 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
|
|||||||
if (server_version == MYSQL_SERVER_VERSION_100)
|
if (server_version == MYSQL_SERVER_VERSION_100)
|
||||||
{
|
{
|
||||||
slave_status.master_host = result->get_string(i_master_host);
|
slave_status.master_host = result->get_string(i_master_host);
|
||||||
slave_status.master_port = result->get_int(i_master_port);
|
slave_status.master_port = result->get_uint(i_master_port);
|
||||||
|
|
||||||
string last_io_error = result->get_string(i_last_io_error);
|
string last_io_error = result->get_string(i_last_io_error);
|
||||||
string last_sql_error = result->get_string(i_last_sql_error);
|
string last_sql_error = result->get_string(i_last_sql_error);
|
||||||
slave_status.last_error = !last_io_error.empty() ? last_io_error : last_sql_error;
|
slave_status.last_error = !last_io_error.empty() ? last_io_error : last_sql_error;
|
||||||
|
|
||||||
int heartbeats = result->get_int(i_slave_rec_hbs);
|
int heartbeats = result->get_uint(i_slave_rec_hbs);
|
||||||
if (slave_heartbeats < heartbeats)
|
if (slave_heartbeats < heartbeats)
|
||||||
{
|
{
|
||||||
latest_event = time(NULL);
|
latest_event = time(NULL);
|
||||||
slave_heartbeats = heartbeats;
|
slave_heartbeats = heartbeats;
|
||||||
heartbeat_period = result->get_int(i_slave_hb_period);
|
heartbeat_period = result->get_uint(i_slave_hb_period);
|
||||||
}
|
}
|
||||||
string using_gtid = result->get_string(i_using_gtid);
|
string using_gtid = result->get_string(i_using_gtid);
|
||||||
if (gtid_domain >= 0 && (using_gtid == "Current_Pos" || using_gtid == "Slave_Pos"))
|
if (gtid_domain >= 0 && (using_gtid == "Current_Pos" || using_gtid == "Slave_Pos"))
|
||||||
@ -291,3 +229,103 @@ bool MariaDBServer::do_show_slave_status(int64_t gtid_domain)
|
|||||||
n_slaves_running = nrunning;
|
n_slaves_running = nrunning;
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MariaDBServer::update_gtids(int64_t gtid_domain)
|
||||||
|
{
|
||||||
|
ss_dassert(gtid_domain >= 0);
|
||||||
|
static const string query = "SELECT @@gtid_current_pos, @@gtid_binlog_pos;";
|
||||||
|
const int ind_current_pos = 0;
|
||||||
|
const int ind_binlog_pos = 1;
|
||||||
|
|
||||||
|
bool rval = false;
|
||||||
|
auto result = execute_query(query);
|
||||||
|
if (result.get() != NULL && result->next_row())
|
||||||
|
{
|
||||||
|
gtid_current_pos = result->get_gtid(ind_current_pos, gtid_domain);
|
||||||
|
gtid_binlog_pos = result->get_gtid(ind_binlog_pos, gtid_domain);
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MariaDBServer::update_replication_settings()
|
||||||
|
{
|
||||||
|
static const string query = "SELECT @@gtid_strict_mode, @@log_bin, @@log_slave_updates;";
|
||||||
|
bool rval = false;
|
||||||
|
auto result = execute_query(query);
|
||||||
|
if (result.get() != NULL && result->next_row())
|
||||||
|
{
|
||||||
|
rpl_settings.gtid_strict_mode = result->get_bool(0);
|
||||||
|
rpl_settings.log_bin = result->get_bool(1);
|
||||||
|
rpl_settings.log_slave_updates = result->get_bool(2);
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MariaDBServer::read_server_variables()
|
||||||
|
{
|
||||||
|
MXS_MONITORED_SERVER* database = server_base;
|
||||||
|
string query = "SELECT @@global.server_id, @@read_only;";
|
||||||
|
int columns = 2;
|
||||||
|
if (version == MYSQL_SERVER_VERSION_100)
|
||||||
|
{
|
||||||
|
query.erase(query.end() - 1);
|
||||||
|
query += ", @@global.gtid_domain_id;";
|
||||||
|
columns = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ind_id = 0;
|
||||||
|
int ind_ro = 1;
|
||||||
|
int ind_domain = 2;
|
||||||
|
auto result = execute_query(query);
|
||||||
|
if (result.get() != NULL && result->next_row())
|
||||||
|
{
|
||||||
|
int64_t server_id_parsed = result->get_uint(ind_id);
|
||||||
|
if (server_id_parsed < 0)
|
||||||
|
{
|
||||||
|
server_id_parsed = SERVER_ID_UNKNOWN;
|
||||||
|
}
|
||||||
|
database->server->node_id = server_id_parsed;
|
||||||
|
server_id = server_id_parsed;
|
||||||
|
read_only = result->get_bool(ind_ro);
|
||||||
|
if (columns == 3)
|
||||||
|
{
|
||||||
|
gtid_domain_id = result->get_uint(ind_domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MariaDBServer::check_replication_settings(print_repl_warnings_t print_warnings)
|
||||||
|
{
|
||||||
|
bool rval = true;
|
||||||
|
const char* servername = server_base->server->unique_name;
|
||||||
|
if (rpl_settings.log_bin == false)
|
||||||
|
{
|
||||||
|
if (print_warnings == WARNINGS_ON)
|
||||||
|
{
|
||||||
|
const char NO_BINLOG[] =
|
||||||
|
"Slave '%s' has binary log disabled and is not a valid promotion candidate.";
|
||||||
|
MXS_WARNING(NO_BINLOG, servername);
|
||||||
|
}
|
||||||
|
rval = false;
|
||||||
|
}
|
||||||
|
else if (print_warnings == WARNINGS_ON)
|
||||||
|
{
|
||||||
|
if (rpl_settings.gtid_strict_mode == false)
|
||||||
|
{
|
||||||
|
const char NO_STRICT[] =
|
||||||
|
"Slave '%s' has gtid_strict_mode disabled. Enabling this setting is recommended. "
|
||||||
|
"For more information, see https://mariadb.com/kb/en/library/gtid/#gtid_strict_mode";
|
||||||
|
MXS_WARNING(NO_STRICT, servername);
|
||||||
|
}
|
||||||
|
if (rpl_settings.log_slave_updates == false)
|
||||||
|
{
|
||||||
|
const char NO_SLAVE_UPDATES[] =
|
||||||
|
"Slave '%s' has log_slave_updates disabled. It is a valid candidate but replication "
|
||||||
|
"will break for lagging slaves if '%s' is promoted.";
|
||||||
|
MXS_WARNING(NO_SLAVE_UPDATES, servername, servername);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
@ -27,38 +27,10 @@ enum mysql_server_version
|
|||||||
MYSQL_SERVER_VERSION_51
|
MYSQL_SERVER_VERSION_51
|
||||||
};
|
};
|
||||||
|
|
||||||
class Gtid
|
enum print_repl_warnings_t
|
||||||
{
|
{
|
||||||
public:
|
WARNINGS_ON,
|
||||||
uint32_t domain;
|
WARNINGS_OFF
|
||||||
int64_t server_id; // Is actually 32bit unsigned. 0 is only used by server versions <= 10.1
|
|
||||||
uint64_t sequence;
|
|
||||||
Gtid();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a Gtid-triplet from a string. In case of a multi-triplet value, only the triplet with
|
|
||||||
* the given domain is returned.
|
|
||||||
*
|
|
||||||
* @param str Gtid string
|
|
||||||
* @param search_domain The Gtid domain whose triplet should be returned. Negative domain stands for
|
|
||||||
* autoselect, which is only allowed when the string contains one triplet.
|
|
||||||
*/
|
|
||||||
Gtid(const char* str, int64_t search_domain = -1);
|
|
||||||
|
|
||||||
bool operator == (const Gtid& rhs) const;
|
|
||||||
|
|
||||||
std::string to_string() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a MASTER_GTID_WAIT()-query to this gtid.
|
|
||||||
*
|
|
||||||
* @param timeout Maximum wait time in seconds
|
|
||||||
* @return The query
|
|
||||||
*/
|
|
||||||
std::string generate_master_gtid_wait_cmd(double timeout) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void parse_triplet(const char* str);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Contains data returned by one row of SHOW ALL SLAVES STATUS
|
// Contains data returned by one row of SHOW ALL SLAVES STATUS
|
||||||
@ -155,4 +127,33 @@ public:
|
|||||||
* @return True on success
|
* @return True on success
|
||||||
*/
|
*/
|
||||||
bool do_show_slave_status(int64_t gtid_domain);
|
bool do_show_slave_status(int64_t gtid_domain);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query gtid_current_pos and gtid_binlog_pos and save the values to the server.
|
||||||
|
* Only the given domain is parsed.
|
||||||
|
*
|
||||||
|
* @param gtid_domain Which gtid domain should be parsed
|
||||||
|
* @return True if successful
|
||||||
|
*/
|
||||||
|
bool update_gtids(int64_t gtid_domain);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query a few miscellaneous replication settings.
|
||||||
|
*
|
||||||
|
* @return True on success
|
||||||
|
*/
|
||||||
|
bool update_replication_settings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query and save server_id, read_only and (if 10.X) gtid_domain_id.
|
||||||
|
*/
|
||||||
|
void read_server_variables();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if server has binary log enabled. Print warnings if gtid_strict_mode or log_slave_updates is off.
|
||||||
|
*
|
||||||
|
* @param print_on Print warnings or not
|
||||||
|
* @return True if log_bin is on
|
||||||
|
*/
|
||||||
|
bool check_replication_settings(print_repl_warnings_t print_warnings = WARNINGS_ON);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -177,12 +177,21 @@ string QueryResult::get_string(int64_t column_ind) const
|
|||||||
return data ? data : "";
|
return data ? data : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t QueryResult::get_int(int64_t column_ind) const
|
int64_t QueryResult::get_uint(int64_t column_ind) const
|
||||||
{
|
{
|
||||||
ss_dassert(column_ind < m_columns);
|
ss_dassert(column_ind < m_columns);
|
||||||
char* data = m_rowdata[column_ind];
|
char* data = m_rowdata[column_ind];
|
||||||
|
int64_t rval = -1;
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
errno = 0; // strtoll sets this
|
errno = 0; // strtoll sets this
|
||||||
return data ? strtoll(data, NULL, 10) : 0;
|
auto parsed = strtoll(data, NULL, 10);
|
||||||
|
if (parsed >= 0 && errno == 0)
|
||||||
|
{
|
||||||
|
rval = parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QueryResult::get_bool(int64_t column_ind) const
|
bool QueryResult::get_bool(int64_t column_ind) const
|
||||||
@ -191,3 +200,77 @@ bool QueryResult::get_bool(int64_t column_ind) const
|
|||||||
char* data = m_rowdata[column_ind];
|
char* data = m_rowdata[column_ind];
|
||||||
return data ? (strcmp(data,"Y") == 0 || strcmp(data, "1") == 0) : false;
|
return data ? (strcmp(data,"Y") == 0 || strcmp(data, "1") == 0) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Gtid QueryResult::get_gtid(int64_t column_ind, int64_t gtid_domain) const
|
||||||
|
{
|
||||||
|
ss_dassert(column_ind < m_columns);
|
||||||
|
char* data = m_rowdata[column_ind];
|
||||||
|
Gtid rval;
|
||||||
|
if (data && *data)
|
||||||
|
{
|
||||||
|
rval = Gtid(data, gtid_domain);
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtid::Gtid()
|
||||||
|
: domain(0)
|
||||||
|
, server_id(SERVER_ID_UNKNOWN)
|
||||||
|
, sequence(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Gtid::Gtid(const char* str, int64_t search_domain)
|
||||||
|
: domain(0)
|
||||||
|
, server_id(SERVER_ID_UNKNOWN)
|
||||||
|
, sequence(0)
|
||||||
|
{
|
||||||
|
// Autoselect only allowed with one triplet
|
||||||
|
ss_dassert(search_domain >= 0 || strchr(str, ',') == NULL);
|
||||||
|
parse_triplet(str);
|
||||||
|
if (search_domain >= 0 && domain != search_domain)
|
||||||
|
{
|
||||||
|
// Search for the correct triplet.
|
||||||
|
bool found = false;
|
||||||
|
for (const char* next_triplet = strchr(str, ',');
|
||||||
|
next_triplet != NULL && !found;
|
||||||
|
next_triplet = strchr(next_triplet, ','))
|
||||||
|
{
|
||||||
|
parse_triplet(++next_triplet);
|
||||||
|
if (domain == search_domain)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ss_dassert(found);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gtid::operator == (const Gtid& rhs) const
|
||||||
|
{
|
||||||
|
return domain == rhs.domain &&
|
||||||
|
server_id != SERVER_ID_UNKNOWN && server_id == rhs.server_id &&
|
||||||
|
sequence == rhs.sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
string Gtid::to_string() const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
if (server_id != SERVER_ID_UNKNOWN)
|
||||||
|
{
|
||||||
|
ss << domain << "-" << server_id << "-" << sequence;
|
||||||
|
}
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gtid::parse_triplet(const char* str)
|
||||||
|
{
|
||||||
|
ss_debug(int rv = ) sscanf(str, "%" PRIu32 "-%" PRId64 "-%" PRIu64, &domain, &server_id, &sequence);
|
||||||
|
ss_dassert(rv == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
string Gtid::generate_master_gtid_wait_cmd(double timeout) const
|
||||||
|
{
|
||||||
|
std::stringstream query_ss;
|
||||||
|
query_ss << "SELECT MASTER_GTID_WAIT(\"" << to_string() << "\", " << timeout << ");";
|
||||||
|
return query_ss.str();
|
||||||
|
}
|
||||||
@ -72,6 +72,40 @@ string get_connection_errors(const ServerVector& servers);
|
|||||||
*/
|
*/
|
||||||
string monitored_servers_to_string(const ServerVector& array);
|
string monitored_servers_to_string(const ServerVector& array);
|
||||||
|
|
||||||
|
class Gtid
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint32_t domain;
|
||||||
|
int64_t server_id; // Is actually 32bit unsigned. 0 is only used by server versions <= 10.1
|
||||||
|
uint64_t sequence;
|
||||||
|
Gtid();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a Gtid-triplet from a string. In case of a multi-triplet value, only the triplet with
|
||||||
|
* the given domain is returned.
|
||||||
|
*
|
||||||
|
* @param str Gtid string
|
||||||
|
* @param search_domain The Gtid domain whose triplet should be returned. Negative domain stands for
|
||||||
|
* autoselect, which is only allowed when the string contains one triplet.
|
||||||
|
*/
|
||||||
|
Gtid(const char* str, int64_t search_domain = -1);
|
||||||
|
|
||||||
|
bool operator == (const Gtid& rhs) const;
|
||||||
|
|
||||||
|
std::string to_string() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a MASTER_GTID_WAIT()-query to this gtid.
|
||||||
|
*
|
||||||
|
* @param timeout Maximum wait time in seconds
|
||||||
|
* @return The query
|
||||||
|
*/
|
||||||
|
std::string generate_master_gtid_wait_cmd(double timeout) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parse_triplet(const char* str);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for simplifying working with resultsets. Used in MariaDBServer.
|
* Helper class for simplifying working with resultsets. Used in MariaDBServer.
|
||||||
*/
|
*/
|
||||||
@ -124,13 +158,12 @@ public:
|
|||||||
string get_string(int64_t column_ind) const;
|
string get_string(int64_t column_ind) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read an integer value from the current row and given column. No error checking is done on the parsing.
|
* Read a non-negative integer value from the current row and given column.
|
||||||
* The parsing is performed by @c strtoll(), so the caller may check errno for errors.
|
|
||||||
*
|
*
|
||||||
* @param column_ind Column index
|
* @param column_ind Column index
|
||||||
* @return Value as integer
|
* @return Value as integer. 0 or greater indicates success, -1 is returned on error.
|
||||||
*/
|
*/
|
||||||
int64_t get_int(int64_t column_ind) const;
|
int64_t get_uint(int64_t column_ind) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a boolean value from the current row and given column.
|
* Read a boolean value from the current row and given column.
|
||||||
@ -140,6 +173,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool get_bool(int64_t column_ind) const;
|
bool get_bool(int64_t column_ind) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a gtid values from the current row and given column. If the field is empty, will return an invalid
|
||||||
|
* gtid.
|
||||||
|
*
|
||||||
|
* @param column_ind Column index
|
||||||
|
* @param gtid_domain Which gtid domain to parse
|
||||||
|
* @return Value as a gtid.
|
||||||
|
*/
|
||||||
|
Gtid get_gtid(int64_t column_ind, int64_t gtid_domain) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MYSQL_RES* m_resultset; // Underlying result set, freed at dtor.
|
MYSQL_RES* m_resultset; // Underlying result set, freed at dtor.
|
||||||
std::tr1::unordered_map<string, int64_t> m_col_indexes; // Map of column name -> index
|
std::tr1::unordered_map<string, int64_t> m_col_indexes; // Map of column name -> index
|
||||||
|
|||||||
Reference in New Issue
Block a user