暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL高可用工具—orchestrator discovery 实例代码浅析

搬砖DBA 2021-04-21
1324


对于MySQL高可用方案,当前比较火的一个技术产品是orchestrator,本文不打算介绍它的整体功能及架构,相关内容可以在https://github.com/openark/orchestrator上查看手册。本文会详细介绍orchestrator discovery功能的大体流程,帮助大家理解orchestrator是怎么对一个实例、集群进行信息收集和维护的。



database_instance表

    CREATE TABLE `database_instance` (
    `hostname` varchar(128) NOT NULL,
    `port` smallint(5) unsigned NOT NULL,
    `last_checked` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `last_attempted_check` timestamp NOT NULL DEFAULT '1971-01-01 00:00:00',
    `last_check_partial_success` tinyint(3) unsigned NOT NULL,
    `last_seen` timestamp NULL DEFAULT NULL,
    `uptime` int(10) unsigned NOT NULL,
    `server_id` int(10) unsigned NOT NULL,
    `server_uuid` varchar(64) NOT NULL,
    `version` varchar(128) NOT NULL,
    `binlog_server` tinyint(3) unsigned NOT NULL,
    `read_only` tinyint(3) unsigned NOT NULL,
    `binlog_format` varchar(16) NOT NULL,
    `log_bin` tinyint(3) unsigned NOT NULL,
    `log_slave_updates` tinyint(3) unsigned NOT NULL,
    `binary_log_file` varchar(128) NOT NULL,
    `binary_log_pos` bigint(20) unsigned NOT NULL,
    `master_host` varchar(128) NOT NULL,
    `master_port` smallint(5) unsigned NOT NULL,
    `slave_sql_running` tinyint(3) unsigned NOT NULL,
    `slave_io_running` tinyint(3) unsigned NOT NULL,
    `replication_sql_thread_state` tinyint(4) NOT NULL DEFAULT '0',
    `replication_io_thread_state` tinyint(4) NOT NULL DEFAULT '0',
    `has_replication_filters` tinyint(3) unsigned NOT NULL,
    `oracle_gtid` tinyint(3) unsigned NOT NULL,
    `master_uuid` varchar(64) NOT NULL,
    `ancestry_uuid` text NOT NULL,
    `executed_gtid_set` text NOT NULL,
    `gtid_purged` text NOT NULL,
    `gtid_errant` text NOT NULL,
    `supports_oracle_gtid` tinyint(3) unsigned NOT NULL,
    `mariadb_gtid` tinyint(3) unsigned NOT NULL,
    `pseudo_gtid` tinyint(3) unsigned NOT NULL,
    `master_log_file` varchar(128) NOT NULL,
    `read_master_log_pos` bigint(20) unsigned NOT NULL,
    `relay_master_log_file` varchar(128) NOT NULL,
    `exec_master_log_pos` bigint(20) unsigned NOT NULL,
    `relay_log_file` varchar(128) NOT NULL,
    `relay_log_pos` bigint(20) unsigned NOT NULL,
    `last_sql_error` text NOT NULL,
    `last_io_error` text NOT NULL,
    `seconds_behind_master` bigint(20) unsigned DEFAULT NULL,
    `slave_lag_seconds` bigint(20) unsigned DEFAULT NULL,
    `sql_delay` int(10) unsigned NOT NULL,
    `allow_tls` tinyint(3) unsigned NOT NULL,
    `num_slave_hosts` int(10) unsigned NOT NULL,
    `slave_hosts` text NOT NULL,
    `cluster_name` varchar(128) NOT NULL,
    `suggested_cluster_alias` varchar(128) NOT NULL,
    `data_center` varchar(32) NOT NULL,
    `physical_environment` varchar(32) NOT NULL,
    `instance_alias` varchar(128) NOT NULL,
    `semi_sync_enforced` tinyint(3) unsigned NOT NULL,
    `replication_depth` tinyint(3) unsigned NOT NULL,
    `is_co_master` tinyint(3) unsigned NOT NULL,
    `replication_credentials_available` tinyint(3) unsigned NOT NULL,
    `has_replication_credentials` tinyint(3) unsigned NOT NULL,
    `version_comment` varchar(128) NOT NULL DEFAULT '',
    `major_version` varchar(16) NOT NULL,
    `binlog_row_image` varchar(16) NOT NULL,
    `last_discovery_latency` bigint(20) NOT NULL,
    `semi_sync_master_enabled` tinyint(3) unsigned NOT NULL,
    `semi_sync_replica_enabled` tinyint(3) unsigned NOT NULL,
    `gtid_mode` varchar(32) NOT NULL,
    PRIMARY KEY (`hostname`,`port`),
    KEY `cluster_name_idx_database_instance` (`cluster_name`),
    KEY `last_checked_idx_database_instance` (`last_checked`),
    KEY `last_seen_idx_database_instance` (`last_seen`),
    KEY `master_host_port_idx_database_instance` (`master_host`,`master_port`),
    KEY `suggested_cluster_alias_idx_database_instance` (`suggested_cluster_alias`)
    ) ENGINE=InnoDB DEFAULT CHARSET=ascii

    这个表是orchestrator的一个非常重要的表,用来保存探测实例的信息,为后续判断实例是否存活提供基数据。


    探测机制

      func ContinuousDiscovery() {
        //省略若干行代码
        go handleDiscoveryRequests()
      //省略若干行代码
      }

      ContinuousDiscovery()函数是主要功能入口函数,它实现了异步发现、实例信息收集、探测实例失败、执行拓扑恢复等功能。handleDiscoveryRequests()实现并发执行discover的功能函数。

        // handleDiscoveryRequests iterates the discoveryQueue channel and calls upon
        // instance discovery per entry.
        func handleDiscoveryRequests() {
          discoveryQueue = discovery.CreateOrReturnQueue("DEFAULT")
        // create a pool of discovery workers
        for i := uint(0); i < config.Config.DiscoveryMaxConcurrency; i++ {
        go func() {
        for {
                instanceKey := discoveryQueue.Consume()
        // Possibly this used to be the elected node, but has
        // been demoted, while still the queue is full.
        if !IsLeaderOrActive() {
        log.Debugf("Node apparently demoted. Skipping discovery of %+v. "+
        "Remaining queue size: %+v", instanceKey, discoveryQueue.QueueLen())
        discoveryQueue.Release(instanceKey)
        continue
                }
        DiscoverInstance(instanceKey)
        discoveryQueue.Release(instanceKey)
        }
        }()
        }
        }

        会创建一个discoveryQueue进行discover,开启DiscoveryMaxConcurrency(默认300)个并发执行。

        instanceKey := discoveryQueue.Consume()从队列中取一个instanceKey,

          type InstanceKey struct {
          Hostname string
          Port int
          }

          instanceKey是InstanceKey类型的结构体对象,包括Hostname、Port成员。取得instanceKey后会传递给DiscoverInstance(instanceKey)进行处理。

            // DiscoverInstance will attempt to discover (poll) an instance (unless
            // it is already up to date) and will also ensure that its master and
            // replicas (if any) are also checked.
            func DiscoverInstance(instanceKey inst.InstanceKey) {
              //省略若干行代码
            // First we've ever heard of this instance. Continue investigation:
              instance, err = inst.ReadTopologyInstanceBufferable(&instanceKey, config.Config.BufferInstanceWrites, latency)


            // Investigate replicas:
            for _, replicaKey := range instance.SlaveHosts.GetInstanceKeys() {
                replicaKey := replicaKey // not needed? no concurrency here?
            if replicaKey.IsValid() {
            discoveryQueue.Push(replicaKey)
            }
            }
            // Investigate master:
            if instance.MasterKey.IsValid() {
            discoveryQueue.Push(instance.MasterKey)
            }
            }

            分析DiscoverInstance中重要的代码,ReeadTopologyInstanceBufferable会返回Instance类型数据,它是一个实例的具体描述。详细成员字段内容请参考https://github.com/openark/orchestrator/blob/master/go/inst/instance.go  Instance结构体。

              type Instance struct {
              Key InstanceKey
              InstanceAlias string
              Uptime uint
              ServerID uint
              ServerUUID string
              Version string
                //省略若干行
              }

              获得一个instance对象后,会把这个instance下的slaves和master依次Push到队列中,以方便对集群相关成员进行discover,这也是为什么我们把一个集群的单个实例加入orchestrator后,它很快就能发现其他实例信息的原因。

              ReadTopologyInstanceBufferable这个函数的内容比较多,我们分块介绍些。详细内容请参考:

              https://github.com/openark/orchestrator/blob/master/go/inst/instance_dao.go 

                func ReadTopologyInstanceBufferable(instanceKey *InstanceKey, bufferWrites bool, latency *stopwatch.NamedStopwatch) (*Instance, error) {
                //省略若干行
                //初始化instance
                instance := NewInstance()


                    //把实例的Uptime保存到instance.Uptime字段
                var dummy string
                // show global status works just as well with 5.6 & 5.7 (5.7 moves variables to performance_schema)
                    err = db.QueryRow("show global status like 'Uptime'").Scan(&dummy, &instance.Uptime) 


                    //把实例的hostname、server_id、version等信息存入instance对象
                var mysqlHostname, mysqlReportHost string
                    err = db.QueryRow("select @@global.hostname, ifnull(@@global.report_host, ''), @@global.server_id, @@global.version, @@global.version_comment, @@global.read_only, @@global.binlog_format, @@global.log_bin, @@global.log_slave_updates").Scan(&mysqlHostname, &mysqlReportHost, &instance.ServerID, &instance.Version, &instance.VersionComment, &instance.ReadOnly, &instance.Binlog_format, &instance.LogBinEnabled, &instance.LogSlaveUpdatesEnabled)
                if err != nil {
                goto Cleanup
                }


                    //如果开启了LogBinEnabled 则把logfile、logpos、Executed_Gtid_Set信息存入instance实例
                go func() {
                defer waitGroup.Done()
                err = sqlutils.QueryRowsMap(db, "show master status", func(m sqlutils.RowMap) error {
                var err error
                instance.SelfBinlogCoordinates.LogFile = m.GetString("File")
                instance.SelfBinlogCoordinates.LogPos = m.GetInt64("Position")
                instance.ExecutedGtidSet = m.GetStringD("Executed_Gtid_Set", "")
                return err
                      })
                     }()
                     
                     
                     //如果实例开启了半同步,则把半同步信息保存到instance
                     waitGroup.Add(1)
                     go func() {
                      defer waitGroup.Done()
                         err = sqlutils.QueryRowsMap(db, "show global status like 'rpl_semi_sync_%_status'", funsqlutils.RowMap) error {
                          if m.GetString("Variable_name") == "Rpl_semi_sync_master_status" {
                          instance.SemiSyncMasterEnabled = (m.GetString("Value") == "ON")
                } else if m.GetString("Variable_name") == "Rpl_semi_sync_slave_status" {
                instance.SemiSyncReplicaEnabled = (m.GetString("Value") == "ON")
                }
                return nil
                })
                     }()
                      
                      
                      //读取实例中gtid_mode、gtid_purged等信息存入instance对象。
                go func() {
                defer waitGroup.Done()
                var masterInfoRepositoryOnTable bool
                // Stuff only supported on Oracle MySQL >= 5.6
                // ...
                // @@gtid_mode only available in Orcale MySQL >= 5.6
                // Previous version just issued this query brute-force, but I don't like errors being issued where they shouldn't.
                _ = db.QueryRow("select @@global.gtid_mode, @@global.server_uuid, @@global.gtid_purged, @@global.master_info_repository = 'TABLE', @@global.binlog_row_image").Scan(&instance.GTIDMode, &instance.ServerUUID, &instance.GtidPurged, &masterInfoRepositoryOnTable, &instance.BinlogRowImage)
                if instance.GTIDMode != "" && instance.GTIDMode != "OFF" {
                instance.SupportsOracleGTID = true
                }
                if config.Config.ReplicationCredentialsQuery != "" {
                instance.ReplicationCredentialsAvailable = true
                } else if masterInfoRepositoryOnTable {
                _ = db.QueryRow("select count(*) > 0 and MAX(User_name) != '' from mysql.slave_master_info").Scan(&instance.ReplicationCredentialsAvailable)
                }
                }()


                     //执行show slave status信息,把相关内容保存到instance实例 
                err = sqlutils.QueryRowsMap(db, "show slave status", func(m sqlutils.RowMap) error {
                instance.HasReplicationCredentials = (m.GetString("Master_User") != "")
                instance.Slave_IO_Running = (m.GetString("Slave_IO_Running") == "Yes")
                if isMaxScale110 {
                // Covering buggy MaxScale 1.1.0
                instance.Slave_IO_Running = instance.Slave_IO_Running && (m.GetString("Slave_IO_State") == "Binlog Dump")
                }
                instance.Slave_SQL_Running = (m.GetString("Slave_SQL_Running") == "Yes")
                instance.ReadBinlogCoordinates.LogFile = m.GetString("Master_Log_File")
                instance.ReadBinlogCoordinates.LogPos = m.GetInt64("Read_Master_Log_Pos")
                instance.ExecBinlogCoordinates.LogFile = m.GetString("Relay_Master_Log_File")
                instance.ExecBinlogCoordinates.LogPos = m.GetInt64("Exec_Master_Log_Pos")
                instance.IsDetached, _ = instance.ExecBinlogCoordinates.ExtractDetachedCoordinates()
                instance.RelaylogCoordinates.LogFile = m.GetString("Relay_Log_File")
                instance.RelaylogCoordinates.LogPos = m.GetInt64("Relay_Log_Pos")
                instance.RelaylogCoordinates.Type = RelayLog
                instance.LastSQLError = emptyQuotesRegexp.ReplaceAllString(strconv.QuoteToASCII(m.GetString("Last_SQL_Error")), "")
                instance.LastIOError = emptyQuotesRegexp.ReplaceAllString(strconv.QuoteToASCII(m.GetString("Last_IO_Error")), "")
                instance.SQLDelay = m.GetUintD("SQL_Delay", 0)
                instance.UsingOracleGTID = (m.GetIntD("Auto_Position", 0) == 1)
                instance.UsingMariaDBGTID = (m.GetStringD("Using_Gtid", "No") != "No")
                instance.MasterUUID = m.GetStringD("Master_UUID", "No")
                      instance.HasReplicationFilters = ((m.GetStringD("Replicate_Do_DB""") != "") || (m.GetStringD("Replicate_Ignore_DB""") != "") || (m.GetStringD("Replicate_Do_Table""") != "") || (m.GetStringD("Replicate_Ignore_Table""") != "") || (m.GetStringD("Replicate_Wild_Do_Table""") != "") || (m.GetStringD("Replicate_Wild_Ignore_Table""") != ""))
                masterHostname := m.GetString("Master_Host")
                if isMaxScale110 {
                // Buggy buggy maxscale 1.1.0. Reported Master_Host can be corrupted.
                // Therefore we (currently) take @@hostname (which is masquarading as master host anyhow)
                masterHostname = maxScaleMasterHostname
                }
                masterKey, err := NewResolveInstanceKey(masterHostname, m.GetInt("Master_Port"))
                if err != nil {
                logReadTopologyInstanceError(instanceKey, "NewResolveInstanceKey", err)
                }
                masterKey.Hostname, resolveErr = ResolveHostname(masterKey.Hostname)
                if resolveErr != nil {
                logReadTopologyInstanceError(instanceKey, fmt.Sprintf("ResolveHostname(%q)", masterKey.Hostname), resolveErr)
                }
                instance.MasterKey = *masterKey
                instance.IsDetachedMaster = instance.MasterKey.IsDetached()
                instance.SecondsBehindMaster = m.GetNullInt64("Seconds_Behind_Master")
                if instance.SecondsBehindMaster.Valid && instance.SecondsBehindMaster.Int64 < 0 {
                log.Warningf("Host: %+v, instance.SecondsBehindMaster < 0 [%+v], correcting to 0", instanceKey, instance.SecondsBehindMaster.Int64)
                instance.SecondsBehindMaster.Int64 = 0
                }
                // And until told otherwise:
                      instance.SlaveLagSeconds = instance.SecondsBehindMaster
                instance.AllowTLS = (m.GetString("Master_SSL_Allowed") == "Yes")
                // Not breaking the flow even on error
                slaveStatusFound = true
                return nil
                    })    
                 
                Cleanup:
                waitGroup.Wait()
                //省略若干行
                if instanceFound {
                instance.LastDiscoveryLatency = time.Since(readingStartTime)
                instance.IsLastCheckValid = true
                instance.IsRecentlyChecked = true
                instance.IsUpToDate = true
                latency.Start("backend")
                if bufferWrites {
                enqueueInstanceWrite(instance, instanceFound, err)
                } else {
                WriteInstance(instance, instanceFound, err)
                }
                WriteLongRunningProcesses(&instance.Key, longRunningProcesses)
                lastAttemptedCheckTimer.Stop()
                latency.Stop("backend")
                return instance, nil
                }

                // Something is wrong, could be network-wise. Record that we
                // tried to check the instance. last_attempted_check is also
                // updated on success by writeInstance.
                latency.Start("backend")
                _ = UpdateInstanceLastChecked(&instance.Key, partialSuccess)
                latency.Stop("backend")
                return nil, err
                      //完整内容请参考https://github.com/openark/orchestrator/blob/master/go/inst/instance_dao.go      
                }

                将instance对象信息保存到后端database_instance表。

                  *************************** 1. row ***************************
                                           hostname: 192.168.1.1
                                               port: 3306
                  last_checked: 2021-01-24 12:11:41
                  last_attempted_check: 2021-01-24 12:11:41
                  last_check_partial_success: 1
                  last_seen: 2021-01-24 12:11:41
                  uptime: 42599071
                  server_id: 48301
                  server_uuid: 16db875e-e197-11e8-9c8f-b4969111dff0
                  version: 5.6.32-78.0-log
                  binlog_server: 0
                  read_only: 0
                  binlog_format: ROW
                  log_bin: 1
                  log_slave_updates: 1
                  binary_log_file: mysql-bin.000075
                  binary_log_pos: 583135957
                  master_host:
                  master_port: 0
                  slave_sql_running: 0
                  slave_io_running: 0
                  replication_sql_thread_state: -1
                  replication_io_thread_state: -1
                  has_replication_filters: 0
                  oracle_gtid: 0
                  master_uuid:
                  ancestry_uuid: 16db875e-e197-11e8-9c8f-b4969111dff0
                  executed_gtid_set: 16db875e-e197-11e8-9c8f-b4969111dff0:1-86855534
                  gtid_purged: 16db875e-e197-11e8-9c8f-b4969111dff0:1-83262861
                  gtid_errant:
                  supports_oracle_gtid: 1
                  mariadb_gtid: 0
                  pseudo_gtid: 0
                  master_log_file:
                  read_master_log_pos: 0
                  relay_master_log_file:
                  exec_master_log_pos: 0
                  relay_log_file:
                  relay_log_pos: 0
                  last_sql_error:
                  last_io_error:
                  seconds_behind_master: NULL
                  slave_lag_seconds: NULL
                  sql_delay: 0
                  allow_tls: 0
                  num_slave_hosts: 2
                                        slave_hosts: [{"Hostname":"192.168.1.2","Port":3306},{"Hostname":"192.168.1.3","Port":3306}]
                                       cluster_name: 192.168.1.1:3306
                            suggested_cluster_alias: mysql_test
                  data_center: RW
                  physical_environment:
                                     instance_alias: bjlf-mysql-001.bjlf.com
                  semi_sync_enforced: 0
                  replication_depth: 0
                  is_co_master: 0
                  replication_credentials_available: 0
                  has_replication_credentials: 0
                  version_comment: Percona Server (GPL), Release 78.0, Revision 8a8e016
                  major_version: 5.6
                  binlog_row_image: FULL
                  last_discovery_latency: 10706003
                  semi_sync_master_enabled: 0
                  semi_sync_replica_enabled: 0
                  gtid_mode: ON


                  last_checked、last_attempted_check、last_check_partial_success、last_seen是判断实例健康状态的几个重要字段。


                  last_check_partial_success:从上文中可以看到ReadTopologyInstanceBufferable函数会连接实例获得很多的实例信息,如果函数连接到实例之前异常,那么这个字段为0,如果能连接到实例能获得部分或全部信息这个字段值为1。


                  last_attempted_check:ReadTopologyInstanceBufferable函数开始执行的时候会对instanceKey合法性进行判断,不合法情况下会更新last_attempted_check时间戳为当前时间,返回err信息为:ReadTopologyInstance will not act on invalid instance key。

                  另一个地方更新此字段的地方是ReadTopologyInstanceBufferable做了以下定义:

                      lastAttemptedCheckTimer := time.AfterFunc(time.Second, func() {
                    go UpdateInstanceLastAttemptedCheck(instanceKey)
                    })

                    lastAttemptedCheckTimer会延迟执行,不过如果ReadTopologyInstanceBufferable快于1秒内执行并且能正常discover到实例信息的话,lastAttemptedCheckTimer.Stop()会暂停更新last_attempted_check字段。


                    ReadTopologyInstanceBufferable函数中label Cleanup 代码块定义了相关逻辑,如果能对一个实例正常discover的情况下会执行WriteInstance函数把获得的instance实例信息保存到后端database_instance表里面。保存的过程中会一次性把last_checked、last_attempted_check、last_seen更新成当前时间,把last_check_partial_success更新成1。



                    总结

                    orchestrator会间隔InstancePollSeconds(默认5s)连接实例上拉取实例状态,并将这些状态信息存入orchestrator的元数据库的orchestrator.database_instance表中。获得的状态信息有(NOT MaxScale):

                      show global status like 'Uptime'
                      select @@global.hostname, ifnull(@@global.report_host, ''), @@global.server_id, @@global.version, @@global.version_comment, @@global.read_only, @@global.binlog_format, @@global.log_bin, @@global.log_slave_updates
                      show master status
                      show global status like 'rpl_semi_sync_%_status'
                      select @@global.gtid_mode, @@global.server_uuid, @@global.gtid_executed, @@global.gtid_purged, @@global.master_info_repository = 'TABLE', @@global.binlog_row_image
                      show slave status
                      select count(*) > 0 and MAX(User_name) != '' from mysql.slave_master_info
                      show slave hosts
                      select substring_index(host, ':', 1) as slave_hostname from information_schema.processlist where command IN ('Binlog Dump', 'Binlog Dump GTID')
                      SELECT SUBSTRING_INDEX(@@hostname, '.', 1)


                      获得到实例信息后,通过下面语句将状态值存入到orchestrator的元数据库中:

                        INSERT INTO database_instance
                        (hostname, port, last_checked, last_attempted_check, last_check_partial_success, uptime, server_id, server_uuid, version, major_version, version_comment, binlog_server, read_only, binlog_format, binlog_row_image, log_bin, log_slave_updates, binary_log_file, binary_log_pos, master_host, master_port, slave_sql_running, slave_io_running, replication_sql_thread_state, replication_io_thread_state, has_replication_filters, supports_oracle_gtid, oracle_gtid, master_uuid, ancestry_uuid, executed_gtid_set, gtid_mode, gtid_purged, gtid_errant, mariadb_gtid, pseudo_gtid, master_log_file, read_master_log_pos, relay_master_log_file, exec_master_log_pos, relay_log_file, relay_log_pos, last_sql_error, last_io_error, seconds_behind_master, slave_lag_seconds, sql_delay, num_slave_hosts, slave_hosts, cluster_name, suggested_cluster_alias, data_center, region, physical_environment, replication_depth, is_co_master, replication_credentials_available, has_replication_credentials, allow_tls, semi_sync_enforced, semi_sync_master_enabled, semi_sync_replica_enabled, instance_alias, last_discovery_latency, last_seen)
                        VALUES
                                        ('192.168.1.1', 3306, NOW(), NOW(), 1, 42599071, 48301, '16db875e-e197-11e8-9c8f-b4969111dff0', '5.6.32-78.0-log', '5.6', 'Percona Server (GPL), Release 78.0, Revision 8a8e016', 0, 1, 'ROW', 'FULL', 1, 1, 'mysql-bin.000075', 583135957, '', 0, 1, 1, 1, 1, 0, 1, 1, '16db875e-e197-11e8-9c8f-b4969111dff0', '16db875e-e197-11e8-9c8f-b4969111dff0:1-86855534', '16db875e-e197-11e8-9c8f-b4969111dff0:1-83262861', 'ON', '', '', 0, 0, '', 0, '', , '', 137056344, '', '', 0, 0, 0, 1, '[{\"Hostname\":\"192.168.1.2\",\"Port\":3306}]', '192.168.1.1:3306', 'bjlf-mysql-001.bjlf.com', '', '', '', 1, 1, 1, 1, 0, 0, 0, 0, '', 10706003, NOW())
                        ON DUPLICATE KEY UPDATE
                        hostname=VALUES(hostname), port=VALUES(port), last_checked=VALUES(last_checked), last_attempted_check=VALUES(last_attempted_check), last_check_partial_success=VALUES(last_check_partial_success), uptime=VALUES(uptime), server_id=VALUES(server_id), server_uuid=VALUES(server_uuid), version=VALUES(version), major_version=VALUES(major_version), version_comment=VALUES(version_comment), binlog_server=VALUES(binlog_server), read_only=VALUES(read_only), binlog_format=VALUES(binlog_format), binlog_row_image=VALUES(binlog_row_image), log_bin=VALUES(log_bin), log_slave_updates=VALUES(log_slave_updates), binary_log_file=VALUES(binary_log_file), binary_log_pos=VALUES(binary_log_pos), master_host=VALUES(master_host), master_port=VALUES(master_port), slave_sql_running=VALUES(slave_sql_running), slave_io_running=VALUES(slave_io_running), replication_sql_thread_state=VALUES(replication_sql_thread_state), replication_io_thread_state=VALUES(replication_io_thread_state), has_replication_filters=VALUES(has_replication_filters), supports_oracle_gtid=VALUES(supports_oracle_gtid), oracle_gtid=VALUES(oracle_gtid), master_uuid=VALUES(master_uuid), ancestry_uuid=VALUES(ancestry_uuid), executed_gtid_set=VALUES(executed_gtid_set), gtid_mode=VALUES(gtid_mode), gtid_purged=VALUES(gtid_purged), gtid_errant=VALUES(gtid_errant), mariadb_gtid=VALUES(mariadb_gtid), pseudo_gtid=VALUES(pseudo_gtid), master_log_file=VALUES(master_log_file), read_master_log_pos=VALUES(read_master_log_pos), relay_master_log_file=VALUES(relay_master_log_file), exec_master_log_pos=VALUES(exec_master_log_pos), relay_log_file=VALUES(relay_log_file), relay_log_pos=VALUES(relay_log_pos), last_sql_error=VALUES(last_sql_error), last_io_error=VALUES(last_io_error), seconds_behind_master=VALUES(seconds_behind_master), slave_lag_seconds=VALUES(slave_lag_seconds), sql_delay=VALUES(sql_delay), num_slave_hosts=VALUES(num_slave_hosts), slave_hosts=VALUES(slave_hosts), cluster_name=VALUES(cluster_name), suggested_cluster_alias=VALUES(suggested_cluster_alias), data_center=VALUES(data_center), region=VALUES(region), physical_environment=VALUES(physical_environment), replication_depth=VALUES(replication_depth), is_co_master=VALUES(is_co_master), replication_credentials_available=VALUES(replication_credentials_available), has_replication_credentials=VALUES(has_replication_credentials), allow_tls=VALUES(allow_tls), semi_sync_enforced=VALUES(semi_sync_enforced), semi_sync_master_enabled=VALUES(semi_sync_master_enabled), semi_sync_replica_enabled=VALUES(semi_sync_replica_enabled), instance_alias=VALUES(instance_alias), last_discovery_latency=VALUES(last_discovery_latency), last_seen=VALUES(last_seen)



                        后期会针对orchestrator探测实例失败的流程进行分析,敬请期待。





                        文章转载自搬砖DBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                        评论