From 4cb6d9227e1e95fa3991b11159a9b1ed0e0ac145 Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Mon, 17 Oct 2016 07:20:35 +0300 Subject: [PATCH] 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. --- server/modules/monitor/mysqlmon/mysql_mon.c | 30 ++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/server/modules/monitor/mysqlmon/mysql_mon.c b/server/modules/monitor/mysqlmon/mysql_mon.c index 901238f44..86967962d 100644 --- a/server/modules/monitor/mysqlmon/mysql_mon.c +++ b/server/modules/monitor/mysqlmon/mysql_mon.c @@ -49,6 +49,7 @@ #include #include #include +#include /** 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