如何在mysql主从中确定master

Eth*_*yon 21 mysql replication

我正在设置 MySQL 主从复制,并且我试图弄清楚如何处理故障转移情况,在这种情况下,我将从站提升为主站(在主站出现故障的情况下)。

我的应用程序服务器需要将所有写入定向到当前主服务器,但我不能在主服务器和从服务器之间使用服务器级 HA(心跳、保持活动),因为两个数据库服务器位于不同物理位置的完全不同的子网上。

我认为这是我需要在应用程序级别处理的事情。我可以查询两台服务器并询问哪一台是主服务器,然后对那一台执行所有查询。

MySQL中有没有查询当前服务器是否是主从副本中的master?

Mic*_*bot 19

@RolandoMySQLDBA 准确地回答了这个问题……但他也指出他的解决方案是“快速而肮脏的”。

这是一个非常真实的陈述。:)

在这里让我担心的不是那个答案,而是最初的问题似乎做出了错误的假设:

我可以查询两台服务器并询问哪一台是主服务器,然后对那一台执行所有查询。

问题是在 MySQL 复制中,master 永远不会真正意识到它是 master。

“升主”的概念在 MySQL 异步复制中并不是真正的概念。将 MySQL 服务器“提升”为主角色是在 MySQL 服务器“外部”发生的事情,而不是在 MySQL 服务器“内部”发生的事情。

“升级到主服务器”不是通过任何类型的服务器配置完成的,因为从技术上讲,每个启用了二进制日志的 MySQL 服务器都是主服务器,即使它从来没有从服务器。 SHOW MASTER STATUS以完全相同的方式工作并返回完全相同的结果,无论是否为从站,并且具有 2 个从站的主站与具有 1 个从站或 0 个从站的主站相同或多或少是主站。类似地,一个从节点都离线的主节点仍然是一个主节点,因为当从节点重新上线时,它们会从上次中断的地方继续复制。

从某种意义上说,任一服务器的唯一“意识”不是它是否是主服务器,而是它是否是从服务器(或“不是”)。

罗兰多的解法就是这么问的:“你是奴隶吗?” 如果答案是否定的,那么假设这一定是主人……如果STOP SLAVE;发布,他也指出这是一个有缺陷的假设。但是停止的奴隶仍然是奴隶,所以“不是奴隶”(在任何时候)并不等同于“成为主人”。

可以在假定的主人上进行类似的测试:

SELECT COUNT(1) FROM information_schema.processlist
 WHERE user = 'the_username_used_by_the_slave';
Run Code Online (Sandbox Code Playgroud)

或者

SELECT COUNT(1) FROM information_schema.processlist
 WHERE command = 'binlog dump';
Run Code Online (Sandbox Code Playgroud)

如果该值为零,则从站的 IO 线程未连接。这个测试有一个类似的缺陷,如果从管理断开、隔离或失败,那么它就不会连接。所以这也不能真正解决任何问题。

更糟糕的是(对于这两种情况),information_schema.processlist“表”是一个虚拟表,每次从中选择它时都会被物化,这需要时间和资源。你的服务器越忙,成本就越高,因为每个线程的活动都必须被窥视。

更轻量级的解决方案是:

SELECT @@global.read_only;
Run Code Online (Sandbox Code Playgroud)

在从站上,您可以/应该设置全局变量,read_only以便没有SUPER权限的用户无法无意中写入它(并且您的应用程序不应该有SUPER)。如果您手动将从站“提升”为主站角色,您SET GLOBAL read_only = OFF将启用写入。(无论如何设置,复制始终可以写入从站)。

但这仍然,我认为,错过了一个重要的点:

我建议应用程序不应该在主/从设置中试探性地做出这个决定,当然也不应该在逐个连接的基础上做出这个决定。 应用程序应该使用硬配置选项,或者应用程序应该保持不知道并让数据库连接目标由其他东西处理。

或者,至少,应用程序不应该在主节点失败之前切换,然后它不应该自己切换回来。

这就是我这么说的原因:一旦做出“决定”——由任何人或任何人——让另一台服务器成为主服务器,应用程序不能以任何理由切换回原来的主服务器,即使它重新上线,无需干预。

假设您遇到了一个错误并且发生了软件强制崩溃;mysqld_safe尽职尽责地重新启动mysqld,并且 InnoDB 崩溃恢复执行完美无缺。但这需要几分钟。

同时,主站已关闭,因此您的应用程序已切换到从站。交易已创建、订单已下达、资金转移、评论已发布、博客已编辑,无论您的系统做什么。

现在,原来的主人重新上线了。

如果您的应用程序切换回原来的主服务器,那么您绝对会受到伤害,因为接下来可能会发生的事情是复制由于不一致而停止,因为您的应用程序实际上已经更改了从服务器上的数据时间。您现在有两个数据库服务器的数据不一致,您必须手动协调这些数据。如果涉及美元或积分或信用,则您现在的余额不匹配。

因此,在没有您的干预的情况下,不允许应用程序切换回原始主服务器,这一点至关重要。

等等,你刚才有没有像我描述的那样发现这个场景的问题? 主服务器失败了,但您的应用程序不会使用从服务器,因为它认为从服务器仍然是从服务器而不是主服务器……information_schema.processlist即使主服务器断电,从服务器上的查询仍将返回非零值.

因此,应用程序发现任何内容没有多大意义,因为您必须手动STOP SLAVE进行该测试才能有用。

如果您希望应用程序能够切换,也许更好的方法是使用循环复制配置服务器。

循环复制有其自身固有的问题,但只要您的应用程序始终一次只写入一台服务器,大多数这些问题就不会成为问题。换句话说,在复制的意义上,两台机器总是同时同时是主机和从机,但是您的应用程序,通过某种机制,总是一次只指向一台机器作为它可以并且应该写入的“主机” .

由于它们的分离,您无法在 MySQL 服务器上部署 HA 工具,但您可以通过在应用程序服务器上运行的 HAProxy 来实现它。应用程序连接到本地主机上的“MySQL”,它根本不是 MySQL,但实际上是 HAProxy ......并将 TCP 连接转发到适当的 MySQL 机器。

HAProxy 可以测试与 MySQL 服务器的连接,并且只向接受连接并允许身份验证的 MySQL 机器提供流量。

在应用服务器上运行的 HAProxy 的组合(与应用服务器必须做的其他事情相比,它对资源的需求不会很大——它几乎只是将套接字绑定在一起并忽略它们的有效负载)......和 ​​MySQL 循环复制根据问题中已知的内容,这将是我在这种情况下可能采取的方法。

或者,对于严格的手动设置,使用比“发现”简单得多的东西,例如应用程序服务器/etc/hosts文件中的条目,其中包含应用程序用于连接到 MySQL 的主机名,您可以手动更新 - 假设从服务器升级到master 旨在成为一个手动过程。

或者,使用 Percona XtraDB Cluster 做一些更复杂的事情。但是,为此,您需要添加第三台服务器,因为在 PXC 中有 3 个节点,如果 2 台服务器可以相互看到但与 1 台服务器隔离(如果所有三台服务器仍在运行),则 2 台服务器会继续愉快地运行,但是第一个服务器蜷缩成一个小球并拒绝做任何事情,因为它意识到它一定是奇怪的那个。这是有效的,因为 2 人意识到他们仍然构成了网络分裂之前在线的大多数节点,而 1 人意识到它不是。使用 PXC,您的应用程序连接到哪个服务器并不重要。

我说所有这些都是在说“不要让应用程序轮询服务器以查看哪个是主服务器”,因为它迟早会咬你,并且它会蚕食你的表现,直到它咬人的那一天。


Rol*_*DBA 13

如果您只使用 Master/Slave,这里有一些快速而肮脏的事情:

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';
Run Code Online (Sandbox Code Playgroud)

这告诉你什么?

  • 如果SlaveThreadCount= 0,则您拥有Master
  • 如果SlaveThreadCount> 0,则您拥有 Slave

CAVEAT:只要你不运行,这就有效STOP SLAVE;

另一件要尝试的事情是:如果您在 Slave 上禁用二进制日志记录并运行SHOW MASTER STATUS;,则 Master 会为您提供当前的二进制日志。奴隶什么都不给你。