MXS-778: Set read-only masters into Slave status

When a master server is set into read-only mode, it can be treated as an
always up-to-date slave. This gives us a somewhat graceful way to prevent
writes to a master.

Usually setting the master into read-only mode is done before a change in
the replication topology to prevent stray writes arriving on the
master. MaxScale should respect the read-only mode and not send any writes
to a server that's in read-only mode.
This commit is contained in:
Markus Makela 2016-10-17 07:20:35 +03:00
parent d5cf74bd24
commit 4cb6d9227e

View File

@ -49,6 +49,7 @@
#include <maxscale/dcb.h>
#include <maxscale/modutil.h>
#include <maxscale/alloc.h>
#include <maxscale/debug.h>
/** Column positions for SHOW SLAVE STATUS */
#define MYSQL55_STATUS_BINLOG_POS 5
@ -1032,8 +1033,17 @@ void find_graph_cycles(MYSQL_MONITOR *handle, MONITOR_SERVERS *database, int nse
* slave in this case can be either a normal slave or another
* master.
*/
monitor_set_pending_status(graph[i].db, SERVER_MASTER | SERVER_STALE_STATUS);
monitor_clear_pending_status(graph[i].db, SERVER_SLAVE);
if (graph[i].info->read_only)
{
/** The master is in read-only mode, set it into Slave state */
monitor_set_pending_status(graph[i].db, SERVER_SLAVE);
monitor_clear_pending_status(graph[i].db, SERVER_MASTER | SERVER_STALE_STATUS);
}
else
{
monitor_set_pending_status(graph[i].db, SERVER_MASTER | SERVER_STALE_STATUS);
monitor_clear_pending_status(graph[i].db, SERVER_SLAVE);
}
}
}
}
@ -1315,10 +1325,11 @@ monitorMain(void *arg)
ptr = mon->databases;
while (ptr)
{
MYSQL_SERVER_INFO *serv_info = hashtable_fetch(handle->server_info, ptr->server->unique_name);
ss_dassert(serv_info);
if (!SERVER_IN_MAINT(ptr->server))
{
MYSQL_SERVER_INFO *serv_info = hashtable_fetch(handle->server_info, ptr->server->unique_name);
ss_dassert(serv_info);
/** If "detect_stale_master" option is On, let's use the previous master.
*
* Multi-master mode detects the stale masters in find_graph_cycles().
@ -1327,7 +1338,8 @@ monitorMain(void *arg)
(strcmp(ptr->server->name, root_master->server->name) == 0 &&
ptr->server->port == root_master->server->port) &&
(ptr->server->status & SERVER_MASTER) &&
!(ptr->pending_status & SERVER_MASTER))
!(ptr->pending_status & SERVER_MASTER) &&
!serv_info->read_only)
{
/**
* In this case server->status will not be updated from pending_status
@ -1877,7 +1889,13 @@ static MONITOR_SERVERS *get_replication_tree(MONITOR *mon, int num_servers)
monitor_clear_pending_status(handle->master, SERVER_MASTER);
}
monitor_set_pending_status(master, SERVER_MASTER);
MYSQL_SERVER_INFO* info = hashtable_fetch(handle->server_info,
master->server->unique_name);
ss_dassert(info);
/** Only set the Master status if read_only is disabled */
monitor_set_pending_status(master, info->read_only ? SERVER_SLAVE : SERVER_MASTER);
handle->master = master;
}
else