如何在mysql master-slave中确定master


17

我正在设置MySQL主从复制,并且试图找出如何处理故障转移情况,在这种情况下我会将从提升为主(万一发生故障)。

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

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

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


您正在使用什么版本的MySQL?
RolandoMySQLDBA

这是mysql的输出Server version: 5.5.23 MySQL Community Server (GPL)
Ethan Hayon

Answers:


13

@RolandoMySQLDBA已经正确回答了这个问题……但他还指出,他的解决方案“很脏”。

这是一个非常真实的声明。:)

这里与我有关的不是该答案,而是原始问题似乎做出了错误的假设:

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

问题在于,在MySQL复制中,主服务器永远不会真正意识到它是主服务器。

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

不能通过任何类型的服务器配置来实现“升级为主服务器”,因为从技术上来讲,每个启用了二进制日志记录的MySQL服务器都是主服务器,即使它从来没有从服务器。 SHOW MASTER STATUS无论从机与否,其工作方式完全相同,并返回完全相同的结果,并且具有2个从机的主机比具有1个从机或0个从机的主机或多或少是一个主机。同样,从属服务器都脱机的主服务器仍然与主服务器一样,因为当从属服务器重新联机时,他们将从上次中断的地方进行复制。

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

这就是Rolando的解决方案所要问的:“您是奴隶吗?” 如果答案是否定的,那么假设是,这必须是主......他还指出,作为一个有缺陷的假设,如果STOP SLAVE;发出。但是停止的奴隶仍然是奴隶,因此“(不是奴隶)”(在任何时候)并不等同于“成为主人”。

可以对假定的主服务器执行类似的测试:

SELECT COUNT(1) FROM information_schema.processlist
 WHERE user = 'the_username_used_by_the_slave';

要么

SELECT COUNT(1) FROM information_schema.processlist
 WHERE command = 'binlog dump';

如果该值为零,则说明未连接从站的IO线程。此测试有一个类似的缺陷,即如果从属服务器通过管理方式断开连接,处于隔离状态或发生故障,则它将无法连接。因此,这也无法解决任何问题。

更糟糕的是(对于这两种情况中的任何一种情况)information_schema.processlist“表”都是一个虚拟表,每次从中选择该表时都会具体化,这会花费时间并浪费资源。您的服务器越忙,它的成本就越高,因为每个线程的活动都必须被对等。

一个更轻量级的解决方案是:

SELECT @@global.read_only;

在从属服务器上,您可以/应该设置全局变量,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的,您可以手动更新-假设将slave升级为master是一个手动过程。

或者,使用Percona XtraDB Cluster进行更复杂的处理。但是,为此,您想要添加第三台服务器,因为在PXC中有3个节点,如果2台服务器可以互相看到但与1台服务器隔离(如果所有3台仍在运行),则2台服务器将保持运行,但是1个服务器s缩成一个小球,拒绝执行任何操作,因为它意识到这一定是奇怪的。之所以可行,是因为2意识到它们仍然构成了网络分裂之前在线的大多数节点,而1意识到并非如此。使用PXC,您的应用程序连接到哪个服务器并不重要。

我说的所有这些都是说“不要让应用程序轮询服务器以查看哪个是主服务器”,因为它迟早会咬住您,直到您咬住那一天之前,它都会蚕食您的性能。


首先,感谢您的书面答复。我认为您已经提出了一个好的解决方案。我过去曾考虑过使用循环复制,但是读过一些关于其可靠性的坏东西。但是,通过修改auto_increment_increment,auto_increment_offset等可以避免许多此类问题。在应用程序服务器上本地使用HAProxy(仅作为故障转移)对我们来说将是很好的,因为我们不必修改应用程序,因此可以抽象化故障转移逻辑远离应用程序层。我将研究配置HAProxy,谢谢!
伊桑·海顿

1
乐意效劳。如果您还没有投票,将不胜感激。只要您了解循环复制的工作原理并以明智的方式使用它,循环复制就与主/从复制一样可靠(这是相同的技术,只是双向)。只要服务器正确同步并且应用程序一次只写入一台服务器,我就不会遇到任何问题。该auto_increment_*变量都还是不错的在这种情况下使用,“以防万一”。另外,请记住使用binlog_format= rowmixed-而不是statement(即使您没有循环使用)。
Michael-sqlbot

我更改接受的答案纯粹是因为这个详细的说明帮助我重新架构了系统,使其更强大。@RolandoMySQLDBA的答案仍然是正确的,并且可以解决我最初描述的问题。谢谢!
伊桑·海顿

10

如果仅使用“主/从”,则有些麻烦:

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';

这告诉你什么?

  • 如果SlaveThreadCount= 0,则您拥有
  • 如果SlaveThreadCount> 0,则有从属

CAVEAT:只要您不跑步,此方法就起作用STOP SLAVE;

要尝试的另一件事是:如果在从属服务器上禁用二进制日志记录并运行SHOW MASTER STATUS;,则Master将为您提供当前的二进制日志。奴隶什么也没给你。


太棒了,这正是我所需要的。您是否认为这是解决问题的麻烦方法?我能想到的唯一问题是两台服务器都将升级为主服务器,但这绝不应该真正发生。
伊桑·海顿

如果您需要此答案,请单击我的答案上的对号,以将答案标记为已接受。
RolandoMySQLDBA

我不能再将其标记为接受5分钟:)
Ethan Hayon 2013年

没问题。我很高兴我能帮忙!
RolandoMySQLDBA

0

从mysql提示符
mysql> show slave status 执行此语句;

在从站上显示很多参数及其值/状态,而在主站上则显示为

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.