问题 这是使用mysql实时双向同步动态数据的最佳方法


这是场景。 2个Web服务器位于两个独立的位置,两个mysql数据库具有相同的表。表中的数据预计也是实时相同的。

这是问题所在。如果任一位置的用户同时将新记录输入到相同的表中,如下面的两个第一个表所示,其中每个表中的第三个记录已由不同的人同时输入。表中的数据不再相同。哪种方法能够保持数据实时保持相同,如下表第三表所示,无论更新发生在何处?这样在下面的插图中,而不是在每个表中以3行结束,新记录被双向复制,并且它们被插入到两个表中以再次创建2个相同的表,这次有4列?

Server A in Location A
==============

Table Names
| ID| NAME  |
|-----------|
| 1 | Tom   |
| 2 | Scott |
|-----------|
| 3 | John  |
|-----------|

Server B in Location B
==============
Table Names
| ID| NAME  |
|-----------|
| 1 | Tom   |
| 2 | Scott |
|-----------|
| 3 | Peter |
|-----------|


Expected Scenario
===========
Table Names
| ID| NAME  |
|-----------|
| 1 | Tom   |
| 2 | Scott |
| 3 | Peter |
| 4 | John  |
|-----------|

7123
2017-11-28 13:37


起源



答案:


在两个主服务器上复制数据库没有太多性能。但是,如果您的应用程序编码正确,则会有一点点故障转移。

Master-Master设置与Slave-Master设置基本相同,但两个Slaves都已启动,并且每个盒子上的配置文件都有重要更改。

掌握MySQL 1:

auto_increment_increment = 2
auto_increment_offset = 1 

掌握MySQL 2:

auto_increment_increment = 2
auto_increment_offset = 2

这两个参数确保当两个服务器由于某种原因争夺主键时,它们不会复制并终止复制。默认情况下,任何自动增量字段都将增加2,而不是递增1,而是在一个框中,它将从1开始偏移并运行序列1 3 5 7 9 11 13等。在第二个框中,它将在2处开始偏移并且沿着2 4 6 8 10 12等运行。从当前测试中,自动增量似乎采用下一个空闲数字,而不是之前剩余的数字。例如。如果服务器1插入前3个记录(1 3和5),当服务器2插入第4个时,它将被赋予6的密钥(不是2,未使用)。

一旦你设置了它,就把它们作为奴隶开始。 然后检查两者是否正常工作,连接到两台机器并执行命令 SHOW SLAVE STATUS 你应该注意到这两点 Slave_IO_Running 和 Slave_SQL_Running 应该在每个盒子上都说“是”。

然后,当然,在表中创建一些记录并确保一个框仅插入奇数编号的主键,另一个框仅增加偶数编号的主键。

然后进行所有测试,以确保您可以在每个盒子上执行所有标准应用程序,并将其复制到另一个盒子上。

它一旦开始就相对简单。 但正如已经提到的那样,MySQL确实不鼓励它,并建议您在编写应用程序代码时确保注意到这一功能。

编辑:我认为如果确保偏移正确等理论上可以添加更多主设备。但是,你可能会更现实地添加一些额外的奴隶。


11
2017-11-28 14:13



为了冗余,两个主人应该就足够了。对于负载平衡,可以使用两个位置上的各个主从设置。但是,如果使用具有异地从站的主站,则可以在发生故障时手动切换到该站点,这是另一种选择。 - jishi
另外,请确保服务器具有不同的server-id值,并且replicate-same-server-id设置为默认值0.这可能已经存在,但如果没有,它将循环并遇到错误。 - benlumley
我喜欢让服务器自动增加2的想法,然后编写一个自定义插件来跟踪插入/编辑,插件将处理其余部分。因此,如果服务器1插入(1,3,5),插件可以选择它并使用相同的ID导出到服务器2,反之亦然,因此没有冲突。 - Steve Obbayi
我怀疑你需要编写一个插件才能做到这一点,复制应该这样做。您的连接代码应该只是尝试加载平衡/连接到工作框,复制将完成剩下的工作(因为没有关键冲突,它不应该挣扎)。 - Amadiere


答案:


在两个主服务器上复制数据库没有太多性能。但是,如果您的应用程序编码正确,则会有一点点故障转移。

Master-Master设置与Slave-Master设置基本相同,但两个Slaves都已启动,并且每个盒子上的配置文件都有重要更改。

掌握MySQL 1:

auto_increment_increment = 2
auto_increment_offset = 1 

掌握MySQL 2:

auto_increment_increment = 2
auto_increment_offset = 2

这两个参数确保当两个服务器由于某种原因争夺主键时,它们不会复制并终止复制。默认情况下,任何自动增量字段都将增加2,而不是递增1,而是在一个框中,它将从1开始偏移并运行序列1 3 5 7 9 11 13等。在第二个框中,它将在2处开始偏移并且沿着2 4 6 8 10 12等运行。从当前测试中,自动增量似乎采用下一个空闲数字,而不是之前剩余的数字。例如。如果服务器1插入前3个记录(1 3和5),当服务器2插入第4个时,它将被赋予6的密钥(不是2,未使用)。

一旦你设置了它,就把它们作为奴隶开始。 然后检查两者是否正常工作,连接到两台机器并执行命令 SHOW SLAVE STATUS 你应该注意到这两点 Slave_IO_Running 和 Slave_SQL_Running 应该在每个盒子上都说“是”。

然后,当然,在表中创建一些记录并确保一个框仅插入奇数编号的主键,另一个框仅增加偶数编号的主键。

然后进行所有测试,以确保您可以在每个盒子上执行所有标准应用程序,并将其复制到另一个盒子上。

它一旦开始就相对简单。 但正如已经提到的那样,MySQL确实不鼓励它,并建议您在编写应用程序代码时确保注意到这一功能。

编辑:我认为如果确保偏移正确等理论上可以添加更多主设备。但是,你可能会更现实地添加一些额外的奴隶。


11
2017-11-28 14:13



为了冗余,两个主人应该就足够了。对于负载平衡,可以使用两个位置上的各个主从设置。但是,如果使用具有异地从站的主站,则可以在发生故障时手动切换到该站点,这是另一种选择。 - jishi
另外,请确保服务器具有不同的server-id值,并且replicate-same-server-id设置为默认值0.这可能已经存在,但如果没有,它将循环并遇到错误。 - benlumley
我喜欢让服务器自动增加2的想法,然后编写一个自定义插件来跟踪插入/编辑,插件将处理其余部分。因此,如果服务器1插入(1,3,5),插件可以选择它并使用相同的ID导出到服务器2,反之亦然,因此没有冲突。 - Steve Obbayi
我怀疑你需要编写一个插件才能做到这一点,复制应该这样做。您的连接代码应该只是尝试加载平衡/连接到工作框,复制将完成剩下的工作(因为没有关键冲突,它不应该挣扎)。 - Amadiere


MySQL不支持同步复制,但是,即使它确实如此,您可能也不想使用它(不能在每次事务提交时等待其他服务器同步的性能损失)。

您将不得不考虑更合适的架构解决方案 - 有第三方产品将以预定方式进行合并和解决冲突 - 这是唯一的方法。

期望您的架构以这种方式运行是天真的 - 对于任何数据库都没有“简单修复”,而不仅仅是MySQL。


2
2017-11-28 13:57



它不会像你描述的那样等待 - 如上所述,它实际上是两个主从实例 - benlumley
我的意思是在MySQL支持同步复制的假设情况下。 - MarkR


UID是否相同是否重要?或者您是否想过将远程UID映射到本地UID的表或列,并为希望复制的对象编写自定义同步代码,以便对外键列等进行任何必要的UID映射?


1
2017-11-28 13:49



是的,重要的是UID在两台服务器上是相同的。他们不必遵循顺序,他们只需要在两个服务器中相似和独特。不管怎么说,还是要谢谢你。我非常清楚我会做什么。 - Steve Obbayi


确保表同步的唯一方法是在数据库之间设置双向复制。

但是,MySQL只允许单向复制,因此您无法在此配置中简单地解决问题。

要清楚,您可以“设置”双向复制但MySQL AB 劝阻这个


0
2017-11-28 13:45