Skip to content

Commit 695a5a4

Browse files
committed
Fixing multi source failover for MySQL #459
Fixing super read only for MySQL #459
1 parent 209a8f9 commit 695a5a4

File tree

5 files changed

+98
-55
lines changed

5 files changed

+98
-55
lines changed

cluster/cluster_fail.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -337,12 +337,12 @@ func (cluster *Cluster) MasterFailover(fail bool) bool {
337337
}
338338

339339
if cluster.Conf.ReadOnly {
340-
logs, err = dbhelper.SetReadOnly(cluster.oldMaster.Conn, true)
340+
logs, err = cluster.oldMaster.SetReadOnly()
341341
cluster.LogSQL(logs, err, cluster.oldMaster.URL, "MasterFailover", LvlErr, "Could not set old master as read-only, %s", err)
342-
343-
} else {
344-
logs, err = dbhelper.SetReadOnly(cluster.oldMaster.Conn, false)
345-
cluster.LogSQL(logs, err, cluster.oldMaster.URL, "MasterFailover", LvlErr, "Could not set old master as read-write, %s", err)
342+
/* } else {
343+
logs, err = cluster.oldMaster.SetReadWrite()
344+
cluster.LogSQL(logs, err, cluster.oldMaster.URL, "MasterFailover", LvlErr, "Could not set old master as read-write, %s", err)
345+
*/
346346
}
347347
if cluster.Conf.SwitchDecreaseMaxConn {
348348

cluster/prx_get.go

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -166,48 +166,50 @@ func (proxy *Proxy) GetEnv() map[string]string {
166166

167167
func (proxy *Proxy) GetBaseEnv() map[string]string {
168168
return map[string]string{
169-
"%%ENV:NODES_CPU_CORES%%": proxy.ClusterGroup.Conf.ProvCores,
170-
"%%ENV:SVC_CONF_ENV_MAX_CORES%%": proxy.ClusterGroup.Conf.ProvCores,
171-
"%%ENV:SVC_CONF_ENV_CRC32_ID%%": string(proxy.Id[2:10]),
172-
"%%ENV:SVC_CONF_ENV_SERVER_ID%%": string(proxy.Id[2:10]),
173-
"%%ENV:SVC_CONF_ENV_MYSQL_ROOT_PASSWORD%%": proxy.ClusterGroup.dbPass,
174-
"%%ENV:SVC_CONF_ENV_MYSQL_ROOT_USER%%": proxy.ClusterGroup.dbUser,
175-
"%%ENV:SERVER_IP%%": proxy.GetBindAddress(),
176-
"%%ENV:EXTRA_BIND_SERVER_IPV6%%": proxy.GetBindAddressExtraIPV6(),
177-
"%%ENV:SVC_CONF_ENV_PROXY_USE_SSL%%": proxy.GetUseSSL(),
178-
"%%ENV:CAUSAL_READ%%": proxy.GetCausalRead(),
179-
"%%ENV:SVC_CONF_ENV_PROXY_USE_COMPRESS%%": proxy.GetUseCompression(),
180-
"%%ENV:SERVER_PORT%%": proxy.Port,
181-
"%%ENV:SVC_NAMESPACE%%": proxy.ClusterGroup.Name,
182-
"%%ENV:SVC_NAME%%": proxy.Name,
183-
"%%ENV:SERVERS_HAPROXY_WRITE%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_HAPROXY_WRITE%%"),
184-
"%%ENV:SERVERS_HAPROXY_READ%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_HAPROXY_READ%%"),
185-
"%%ENV:SERVERS_HAPROXY_WRITE_BACKEND%%": proxy.ClusterGroup.Conf.HaproxyAPIWriteBackend,
186-
"%%ENV:SERVERS_HAPROXY_READ_BACKEND%%": proxy.ClusterGroup.Conf.HaproxyAPIReadBackend,
187-
"%%ENV:SVC_CONF_HAPROXY_DNS%%": proxy.GetConfigProxyDNS(),
188-
"%%ENV:SERVERS_PROXYSQL%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_PROXYSQL%%"),
189-
"%%ENV:SERVERS%%": proxy.GetConfigProxyModule("%%ENV:SERVERS%%"),
190-
"%%ENV:SERVERS_LIST%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_LIST%%"),
191-
"%%ENV:SVC_CONF_ENV_PORT_HTTP%%": "80",
192-
"%%ENV:SVC_CONF_ENV_PORT_R_LB%%": strconv.Itoa(proxy.ReadPort),
193-
"%%ENV:SVC_CONF_ENV_PORT_RW%%": strconv.Itoa(proxy.WritePort),
194-
"%%ENV:SVC_CONF_ENV_MAXSCALE_MAXINFO_PORT%%": strconv.Itoa(proxy.ClusterGroup.Conf.MxsMaxinfoPort),
195-
"%%ENV:SVC_CONF_ENV_PORT_RW_SPLIT%%": strconv.Itoa(proxy.ReadWritePort),
196-
"%%ENV:SVC_CONF_ENV_PORT_BINLOG%%": strconv.Itoa(proxy.ClusterGroup.Conf.MxsBinlogPort),
197-
"%%ENV:SVC_CONF_ENV_PORT_TELNET%%": proxy.Port,
198-
"%%ENV:SVC_CONF_ENV_PORT_ADMIN%%": proxy.Port,
199-
"%%ENV:SVC_CONF_ENV_USER_ADMIN%%": proxy.User,
200-
"%%ENV:SVC_CONF_ENV_PASSWORD_ADMIN%%": proxy.Pass,
201-
"%%ENV:SVC_CONF_ENV_SPHINX_MEM%%": proxy.ClusterGroup.Conf.ProvSphinxMem,
202-
"%%ENV:SVC_CONF_ENV_SPHINX_MAX_CHILDREN%%": proxy.ClusterGroup.Conf.ProvSphinxMaxChildren,
203-
"%%ENV:SVC_CONF_ENV_VIP_ADDR%%": proxy.ClusterGroup.Conf.ProvProxRouteAddr,
204-
"%%ENV:SVC_CONF_ENV_VIP_NETMASK%%": proxy.ClusterGroup.Conf.ProvProxRouteMask,
205-
"%%ENV:SVC_CONF_ENV_VIP_PORT%%": proxy.ClusterGroup.Conf.ProvProxRoutePort,
206-
"%%ENV:SVC_CONF_ENV_MRM_API_ADDR%%": proxy.ClusterGroup.Conf.MonitorAddress + ":" + proxy.ClusterGroup.Conf.HttpPort,
207-
"%%ENV:SVC_CONF_ENV_MRM_CLUSTER_NAME%%": proxy.ClusterGroup.GetClusterName(),
208-
"%%ENV:SVC_CONF_ENV_DATADIR%%": proxy.GetConfigDatadir(),
209-
"%%ENV:SVC_CONF_ENV_CONFDIR%%": proxy.GetConfigConfigdir(),
210-
"%%ENV:SVC_CONF_ENV_PROXYSQL_READ_ON_MASTER%%": proxy.GetConfigProxySQLReadOnMaster(),
169+
"%%ENV:NODES_CPU_CORES%%": proxy.ClusterGroup.Conf.ProvCores,
170+
"%%ENV:SVC_CONF_ENV_MAX_CORES%%": proxy.ClusterGroup.Conf.ProvCores,
171+
"%%ENV:SVC_CONF_ENV_CRC32_ID%%": string(proxy.Id[2:10]),
172+
"%%ENV:SVC_CONF_ENV_SERVER_ID%%": string(proxy.Id[2:10]),
173+
"%%ENV:SVC_CONF_ENV_MYSQL_ROOT_PASSWORD%%": proxy.ClusterGroup.dbPass,
174+
"%%ENV:SVC_CONF_ENV_MYSQL_ROOT_USER%%": proxy.ClusterGroup.dbUser,
175+
"%%ENV:SERVER_IP%%": proxy.GetBindAddress(),
176+
"%%ENV:EXTRA_BIND_SERVER_IPV6%%": proxy.GetBindAddressExtraIPV6(),
177+
"%%ENV:SVC_CONF_ENV_PROXY_USE_SSL%%": proxy.GetUseSSL(),
178+
"%%ENV:CAUSAL_READ%%": proxy.GetCausalRead(),
179+
"%%ENV:SVC_CONF_ENV_PROXY_USE_COMPRESS%%": proxy.GetUseCompression(),
180+
"%%ENV:SERVER_PORT%%": proxy.Port,
181+
"%%ENV:SVC_NAMESPACE%%": proxy.ClusterGroup.Name,
182+
"%%ENV:SVC_NAME%%": proxy.Name,
183+
"%%ENV:SERVERS_HAPROXY_WRITE%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_HAPROXY_WRITE%%"),
184+
"%%ENV:SERVERS_HAPROXY_READ%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_HAPROXY_READ%%"),
185+
"%%ENV:SERVERS_HAPROXY_WRITE_BACKEND%%": proxy.ClusterGroup.Conf.HaproxyAPIWriteBackend,
186+
"%%ENV:SERVERS_HAPROXY_READ_BACKEND%%": proxy.ClusterGroup.Conf.HaproxyAPIReadBackend,
187+
"%%ENV:SVC_CONF_HAPROXY_DNS%%": proxy.GetConfigProxyDNS(),
188+
"%%ENV:SERVERS_PROXYSQL%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_PROXYSQL%%"),
189+
"%%ENV:SERVERS%%": proxy.GetConfigProxyModule("%%ENV:SERVERS%%"),
190+
"%%ENV:SERVERS_LIST%%": proxy.GetConfigProxyModule("%%ENV:SERVERS_LIST%%"),
191+
"%%ENV:SVC_CONF_ENV_PORT_HTTP%%": "80",
192+
"%%ENV:SVC_CONF_ENV_PORT_R_LB%%": strconv.Itoa(proxy.ReadPort),
193+
"%%ENV:SVC_CONF_ENV_PORT_RW%%": strconv.Itoa(proxy.WritePort),
194+
"%%ENV:SVC_CONF_ENV_MAXSCALE_MAXINFO_PORT%%": strconv.Itoa(proxy.ClusterGroup.Conf.MxsMaxinfoPort),
195+
"%%ENV:SVC_CONF_ENV_PORT_RW_SPLIT%%": strconv.Itoa(proxy.ReadWritePort),
196+
"%%ENV:SVC_CONF_ENV_PORT_BINLOG%%": strconv.Itoa(proxy.ClusterGroup.Conf.MxsBinlogPort),
197+
"%%ENV:SVC_CONF_ENV_PORT_TELNET%%": proxy.Port,
198+
"%%ENV:SVC_CONF_ENV_PORT_ADMIN%%": proxy.Port,
199+
"%%ENV:SVC_CONF_ENV_USER_ADMIN%%": proxy.User,
200+
"%%ENV:SVC_CONF_ENV_PASSWORD_ADMIN%%": proxy.Pass,
201+
"%%ENV:SVC_CONF_ENV_SPHINX_MEM%%": proxy.ClusterGroup.Conf.ProvSphinxMem,
202+
"%%ENV:SVC_CONF_ENV_SPHINX_MAX_CHILDREN%%": proxy.ClusterGroup.Conf.ProvSphinxMaxChildren,
203+
"%%ENV:SVC_CONF_ENV_VIP_ADDR%%": proxy.ClusterGroup.Conf.ProvProxRouteAddr,
204+
"%%ENV:SVC_CONF_ENV_VIP_NETMASK%%": proxy.ClusterGroup.Conf.ProvProxRouteMask,
205+
"%%ENV:SVC_CONF_ENV_VIP_PORT%%": proxy.ClusterGroup.Conf.ProvProxRoutePort,
206+
"%%ENV:SVC_CONF_ENV_MRM_API_ADDR%%": proxy.ClusterGroup.Conf.MonitorAddress + ":" + proxy.ClusterGroup.Conf.HttpPort,
207+
"%%ENV:SVC_CONF_ENV_MRM_CLUSTER_NAME%%": proxy.ClusterGroup.GetClusterName(),
208+
"%%ENV:SVC_CONF_ENV_DATADIR%%": proxy.GetConfigDatadir(),
209+
"%%ENV:SVC_CONF_ENV_CONFDIR%%": proxy.GetConfigConfigdir(),
210+
"%%ENV:SVC_CONF_ENV_PROXYSQL_READ_ON_MASTER%%": proxy.GetConfigProxySQLReadOnMaster(),
211+
"%%ENV:SVC_CONF_ENV_PROXYSQL_READER_HOSTGROUP%%": proxy.GetConfigProxySQLReaderHostgroup(),
212+
"%%ENV:SVC_CONF_ENV_PROXYSQL_WRITER_HOSTGROUP%%": proxy.GetConfigProxySQLWriterHostgroup(),
211213
}
212214
}
213215

@@ -218,6 +220,14 @@ func (proxy *Proxy) GetConfigProxySQLReadOnMaster() string {
218220
return "0"
219221
}
220222

223+
func (proxy *Proxy) GetConfigProxySQLReaderHostgroup() string {
224+
return strconv.Itoa(proxy.ReaderHostgroup)
225+
}
226+
227+
func (proxy *Proxy) GetConfigProxySQLWriterHostgroup() string {
228+
return strconv.Itoa(proxy.WriterHostgroup)
229+
}
230+
221231
func (proxy *Proxy) GetConfigProxyDNS() string {
222232
if proxy.HasDNS() {
223233
return `

cluster/srv_rejoin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ func (server *ServerMonitor) rejoinSlave(ss dbhelper.SlaveStatus) error {
491491
logs, err := mycurrentmaster.StopSlave()
492492
server.ClusterGroup.LogSQL(logs, err, mycurrentmaster.URL, "Rejoin", LvlErr, "Failed to stop slave on relay server %s: %s", mycurrentmaster.URL, err)
493493
if err == nil {
494-
logs, err2 := dbhelper.MasterPosWait(server.Conn, mycurrentmaster.BinaryLogFile, mycurrentmaster.BinaryLogPos, 3600)
494+
logs, err2 := dbhelper.MasterPosWait(server.Conn, server.DBVersion, mycurrentmaster.BinaryLogFile, mycurrentmaster.BinaryLogPos, 3600, server.ClusterGroup.Conf.MasterConn)
495495
server.ClusterGroup.LogSQL(logs, err2, server.URL, "Rejoin", LvlErr, "Failed positional rejoin wait pos %s %s", server.URL, err2)
496496
if err2 == nil {
497497
myparentss, _ := mycurrentmaster.GetSlaveStatus(mycurrentmaster.ReplicationSourceName)

cluster/srv_wait.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func (server *ServerMonitor) WaitSyncToMaster(master *ServerMonitor) {
2323
server.ClusterGroup.LogSQL(logs, err, server.URL, "MasterFailover", LvlErr, "Failed MasterWaitGTID, %s", err)
2424

2525
} else {
26-
logs, err := dbhelper.MasterPosWait(server.Conn, master.BinaryLogFile, master.BinaryLogPos, 30)
26+
logs, err := dbhelper.MasterPosWait(server.Conn, server.DBVersion, master.BinaryLogFile, master.BinaryLogPos, 30, server.ClusterGroup.Conf.MasterConn)
2727
server.ClusterGroup.LogSQL(logs, err, server.URL, "MasterFailover", LvlErr, "Failed MasterPosWait, %s", err)
2828
}
2929

utils/dbhelper/dbhelper.go

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ type MasterStatus struct {
182182

183183
type SlaveStatus struct {
184184
ConnectionName sql.NullString `db:"Connection_name" json:"connectionName"`
185+
ChannelName sql.NullString `db:"Channel_Name" json:"channelName"`
185186
MasterHost sql.NullString `db:"Master_Host" json:"masterHost"`
186187
MasterUser sql.NullString `db:"Master_User" json:"masterUser"`
187188
MasterPort sql.NullString `db:"Master_Port" json:"masterPort"`
@@ -870,6 +871,13 @@ func GetSlaveStatus(db *sqlx.DB, Channel string, myver *MySQLVersion) (SlaveStat
870871
err = udb.Get(&ss, query)
871872
}
872873
}
874+
//
875+
if ss.ChannelName.Valid {
876+
if ss.ChannelName.String != "" {
877+
ss.ConnectionName.String = ss.ChannelName.String
878+
ss.ConnectionName.Valid = true
879+
}
880+
}
873881

874882
return ss, query, err
875883
}
@@ -879,7 +887,20 @@ func GetChannelSlaveStatus(db *sqlx.DB, myver *MySQLVersion) ([]SlaveStatus, str
879887
udb := db.Unsafe()
880888
ss := []SlaveStatus{}
881889
err := udb.Select(&ss, "SHOW SLAVE STATUS")
882-
return ss, "SHOW SLAVE STATUS", err
890+
// Unified MariaDB MySQL ConnectionName and ChannelName
891+
uniss := []SlaveStatus{}
892+
if err == nil {
893+
for _, s := range ss {
894+
if s.ChannelName.Valid {
895+
if s.ChannelName.String != "" {
896+
s.ConnectionName.String = s.ChannelName.String
897+
s.ConnectionName.Valid = true
898+
}
899+
}
900+
uniss = append(uniss, s)
901+
}
902+
}
903+
return uniss, "SHOW SLAVE STATUS", err
883904
}
884905

885906
func GetPGSlaveStatus(db *sqlx.DB, myver *MySQLVersion) ([]SlaveStatus, error) {
@@ -904,6 +925,7 @@ func GetPGSlaveStatus(db *sqlx.DB, myver *MySQLVersion) ([]SlaveStatus, error) {
904925
ORDER BY pid ASC`
905926

906927
err := udb.Select(&ss, query)
928+
907929
return ss, err
908930
}
909931

@@ -1014,7 +1036,6 @@ func GetAllSlavesStatus(db *sqlx.DB, myver *MySQLVersion) ([]SlaveStatus, string
10141036
(SELECT count(*) as nbrep FROM pg_stat_subscription) AS sqt `
10151037
}
10161038
err = udb.Select(&ss, query)
1017-
10181039
return ss, query, err
10191040
}
10201041

@@ -2214,10 +2235,22 @@ func MasterWaitGTID(db *sqlx.DB, gtid string, timeout int) (string, error) {
22142235
return query + "(" + gtid + "-" + strconv.Itoa(timeout) + ")", err
22152236
}
22162237

2217-
func MasterPosWait(db *sqlx.DB, log string, pos string, timeout int) (string, error) {
2218-
query := "SELECT MASTER_POS_WAIT(?, ?, ?)"
2219-
_, err := db.Exec(query, log, pos, timeout)
2220-
return query + "(" + log + "-" + pos + "-" + strconv.Itoa(timeout) + ")", err
2238+
func MasterPosWait(db *sqlx.DB, myver *MySQLVersion, log string, pos string, timeout int, channel string) (string, error) {
2239+
// SOURCE_POS_WAIT before MySQL 8.0.26
2240+
funcname := "MASTER_POS_WAIT"
2241+
if (myver.Major >= 8 && myver.Minor > 0) || (myver.Major >= 8 && myver.Minor == 0 && myver.Release >= 26) {
2242+
funcname = "SOURCE_POS_WAIT"
2243+
}
2244+
2245+
if channel == "" {
2246+
query := "SELECT " + funcname + "(?, ?, ?)"
2247+
_, err := db.Exec(query, log, pos, timeout)
2248+
return query + "(" + log + "-" + pos + "-" + strconv.Itoa(timeout) + ")", err
2249+
} else {
2250+
query := "SELECT " + funcname + "(?, ?, ?, ?)"
2251+
_, err := db.Exec(query, log, pos, timeout, channel)
2252+
return query + "(" + log + "-" + pos + "-" + strconv.Itoa(timeout) + ")", err
2253+
}
22212254
}
22222255

22232256
func SetReadOnly(db *sqlx.DB, flag bool) (string, error) {

0 commit comments

Comments
 (0)