将主数据库复制到不同的从属

时间:2016-10-07 03:21:22

标签: php mysql phpmyadmin database-replication

我有一个主数据库,它将是由不同学校组成的云服务器。

  

包含每所学校详细信息的仪表板类型。可以编辑他们的信息和其他数据。

现在,这些学校已部署到相应的学校位置,即本地服务器。

  

仪表板类型,只能编辑本地服务器中部署的特定学校。可以编辑他们的信息和其他数据。

现在我想要发生的事情是,如果某些事情发生了变化,就可以同步相应学校的cloud to local server。这也适用于local to cloud server

  

注意:如果你们曾经尝试过Evernote,那么可以在你正在使用的任何设备上编辑笔记信息,并且仍然可以   有互联网或手动点击同步时同步。

     

当本地服务器没有互联网连接并在学校编辑了一些数据时。一旦互联网启动,本地和云服务器的数据应该同步。

     

这就是我追求的逻辑。

enter image description here

有人会为我开始从哪里开始?我无法想出任何适合我问题的解决方案。

我还想到使用php来遍历整个表和对应于当前日期和时间的数据。但我知道那会很糟糕。

已编辑: 我删除了有关此事项的其他SO问题的参考/帖子。

我找到的应用程序挂钩

  • Evernote的
  • Todoist

服务器:

  • 本地服务器计算机:Windows 10(部署在学校中)
  • 云服务器:可能是一些使用phpmyadmin
  • 的专用主机

不要挑剔,但希望答案是你正在和新手谈论掌握到奴隶数据库的过程。我没有这方面的经验。

6 个答案:

答案 0 :(得分:3)

当我们以前这样做时,我们会:

  1. 确保我们要同步的每个表都有Created的日期时间列;改性; &安培;删除。它们也有一个布尔的isDeleted列(所以不是物理删除记录,我们会将它标记为true并在查询中忽略它)。这意味着我们可以查询自特定时间以来已删除的任何记录,并返回这些已删除ID的数组。
  2. 在每个数据库(主服务器和从服务器)中创建一个存储上次成功同步日期时间的表。在master中,这个表存储了多个记录:每个学校1个,但在slave中只需要1个记录 - 最后一次与master同步。
  3. 在你的情况下,每个奴隶都经常这样:

    1. 调用主服务器的Web服务(URL),假设称为“helloMaster”#39;。它将传递学校名称(或某些特定标识符),他们上次成功与主人同步,身份验证详细信息(为了安全),并期望主人回答自该日期以来主人是否有学校的任何更新提供。这里的重点只是寻找主人可用和倾听的确认(即互联网仍在运行)。

    2. 然后,奴隶会打电话给另一个网络服务,让我们称之为“发送更新”。它将再次传入学校名称,上次成功同步,(加上安全认证详细信息)&自上次同步以来,用于任何添加,更新和删除记录的三个数组。主人只是确认收到。如果确认收据,则从属设备移动到步骤3,否则从属设备将在暂停一段时间后再次尝试步骤1。所以现在Master拥有来自奴隶的更新。注意:如果与其挂起的从属更新存在冲突,则由主服务器决定如何合并任何记录。

    3. 奴隶然后打电话给网络服务,让我们说'getUpdates'。它传递学校名称,上次成功同步,安全认证详细信息,&然后,主服务器返回三个数组,用于任何已添加,更新和删除的记录,其中奴隶应该应用于其数据库。

    4. 最后,一旦奴隶试图更新其记录,它将通过另一个网络服务通知主人成功/失败,比如说“updateStatus'”。如果成功,那么主服务器将返回一个新的同步日期供从存储(这将与主服务器在其表中存储的日期完全匹配)。如果失败则会在主站中记录错误,我们会在暂停后返回步骤1.

    5. 我遗漏了一些关于错误处理的细节,让所有设备的时间准确(可能涉及不同的时区),以及其他一些零碎,但这就是它的要点。 / p>

      我可以在考虑更多(或其他人可能编辑我的帖子)之后进行改进。

      希望至少有所帮助。

答案 1 :(得分:3)

我建议你使用琐碎的解决方案,根据我的说法:

  1. 在本地服务器中创建一个SQLlite或任何数据库(MySQL或您选择的)
  2. 保持一个始终运行的线程,该线程将每5分钟ping一次(进行一次API调用)您的主数据库(取决于接受多少延迟)
  3. 通过该主题,您可以检测到您是否已连接到互联网。
  4. 如果连接到互联网

    a)将请求发送到主服务器的本地更改,此主服务器是一个应用程序服务器,它将能够更新学校中本地计算机的更改(您通过API调用收到此更改)到主数据库之后根据您的应用程序使用进行某些验证。

    b)在API调用之后从服务器接收更新的更改,这些更改在解决冲突后提供(例如,如果学校服务器中的数据早于主数据库中更新的数据更新,那么您将根据您的要求接受哪一个)

  5. 如果没有连接到互联网,请继续在本地数据库中存储更改并反映在学校运行的应用程序中的更改,但是当您连接时将这些更改推送到主服务器并拉出实际更改,这是适用来自主服务器。

  6. 这是你自己做的很复杂,但如果规模很小,我宁愿为数据库应用程序实现自己的API,这将以这种方式连接。

    更好的解决方案是使用Google Firebase,这是一个实时数据库,只要有任何机器发生变化,就会异步更新,但如果真的不需要,可能会花费更多。但是,它确实会为您的数据库系统提供Evernote类型的实时编辑功能。

答案 2 :(得分:2)

这不是可以通过数据库复制解决的问题。

一般来说,数据库复制可以以两种模式之一运行:

  • 主/从复制,这是MySQL使用的。在此模式下,所有写入操作必须路由到单个“主”服务器,并且所有副本数据库都会从主服务器接收更改。

    这不符合您的需求,因为只能向主人进行写入。 (直接修改其中一个副本会导致它与主副本永久不同步。)

  • 基于Quorum的复制,由一些较新的数据库使用。所有数据库副本都相互连接。只要所有副本中至少有一半连接(即群集已达到“仲裁”),就可以对任何活动数据库进行写入,并将其传播到所有其他数据库。未连接的数据库将在加入仲裁时更新。

    这也不适合您的需求,因为无法写入断开连接的副本。更糟糕的是,超过一半的副本与主服务器断开连接会阻止剩余的数据库被写入其中!

您需要的是某种数据同步解决方案。任何解决方案都需要一些逻辑 - 您必须编写它们! - 解决冲突。 (例如,如果在学校的本地副本断开连接时在主数据库中修改了记录,并且同样的记录也在那里被修改,则需要一些方法来协调这些差异。)

答案 3 :(得分:1)

无需任何复杂的设置或API。 MySQL允许您轻松复制数据库。 MySQL将确保在互联网可用时正确及时地完成复制。 (也很快)

有:

  1. Master - slave:Master编辑从属读取,换句话说,从主服务器到从服务器的单向同步。
  2. Master - Master:Master1编辑master2读取和编辑,或者换句话说,双向同步。两台服务器都会推送和提取更新。
  3. 假设您的云服务器具有每个学校的架构,并且每个架构都可以通过自己的用户名和密码访问。即db_school1,db_school2

    现在,您可以选择仅将选定的数据库架构从云复制到本地主站。在你的情况下,学校的本地大师只会"复制db_school1"

    如果你只想复制特定的表,MySQL也有这个选项" replicate-do-table"

    实际的复制过程非常简单,但是当你有不同的场景时可以非常深入。

    您想要记录的几件事,服务器ID,每台服务器上的不同自动增量值,以避免与新记录冲突。即Master1生成奇数的记录,偶数的Master 2生成记录,因此不会出现重复的主键问题。服务器关闭警报/监控,错误跳过

    我不确定你是在linux还是windows上,我已经编写了简单的c#应用程序,它检查是否有任何主人因任何原因没有复制或停止并发送电子邮件。监控至关重要!

    这里有一些主要主复制的链接: https://www.howtoforge.com/mysql_master_master_replication

    https://www.digitalocean.com/community/tutorials/how-to-set-up-mysql-master-master-replication

    还值得阅读这个优化的tabl级复制信息: https://dba.stackexchange.com/questions/37015/how-can-i-replicate-some-tables-without-transferring-the-entire-log

    希望这会有所帮助。

答案 4 :(得分:1)

编辑:

这个答案的原始版本提出了MongoDB;但随着进一步的阅读,MongoDB在恶劣的互联网连接上并不那么可靠。 CouchDB专为脱机文档而设计,这是您所需要的 - 尽管不幸的是,它比MongoDB更难获得。

原件:

我建议不要使用MySQL,而是部署专为复制而设计的文档存储,例如CouchDB - 除非您使用商业MySQL集群服务。

作为MySQL的强大爱好者,我发现很难建议你使用别的东西,但在这种情况下,你真的应该。

这就是为什么 -

使用MySQL复制的问题

为什么MySQL有良好的复制(如果你正在同步MySQL数据库,那么你最应该使用的是 - 正如其他人所推荐的那样)有一些需要注意的事项。

  • “独特的钥匙”冲突会给你带来巨大的麻烦;最多 可能的原因是“自动递增”中常见的ID MySQL应用程序(除非有,否则不要将它们用于同步操作 是一个明确的“读+写” - >“只读”关系 - 没有 在你的情况下。)
  • 主键必须由每个服务器生成,但在所有服务器上都是唯一的。可能通过为该服务器添加服务器标识符和唯一ID的混合(Server1_1,Server1_2,Server1_3等不会与Server2_1冲突)
  • MySQL同步仅支持在线,除非您查看其群集解决方案(https://www.mysql.com/products/cluster/)。

使用时间戳记录“手动”执行此操作时出现问题。

另一个答案建议保留“时间更新”记录。虽然我已经采用了这种方法,但仍有一些需要注意的问题。

使用日记功能“手动”执行此操作时出现问题。

Journalling正在单独记录已发生变化的内容和时间。 “数据库X,表Y,字段Z在时间B更新为值A”或“表A新记录添加了这些详细信息[...]”。这使您可以更好地控制要更新的内容。

  • 如果你看一下数据库同步技术,这实际上是后台发生的事情;在MySQL的情况下,它保留了更新的二进制日志
  • 你只是分享期刊,而不是原创的记录。
  • 当另一台服务器收到日记帐分录时,如果能够更好地了解之前/之后发生的事情,可以重播更新并确保您获得正确的详细信息。
  • 当日志/数据库失去同步时会出现问题(当发生这种情况时,MySQL实际上是一种痛苦!)。您需要准备好一个“刷新”脚本,该脚本位于日志记录之外,以便将数据库同步到主服务器。
  • 这很复杂。所以...

解决方案:使用专为复制而设计的文档存储,例如MongoDB的

考虑到这一切,为什么不使用已经为您完成所有这些工作的文档存储? CouchDB支持并处理所有日记和同步(http://docs.couchdb.org/en/master/replication/protocol.html)。

还有其他人,但我相信与其他解决方案相比,你最终会减少头痛和错误。

答案 5 :(得分:1)

使用auto_increment时,可以在不违反密钥的情况下完成MySQL中的主控复制。这是一个解释如何的链接。

如果你的表没有主键,我不确定会发生什么(我总是在表上包含auto_increment主键)

http://brendanschwartz.com/post/12702901390/mysql-master-master-replication

自动增量偏移和自动增量增量会影响auto_increment值,如文章中的配置示例所示......

server_id           = 1
log_bin             = /var/log/mysql/mysql-bin.log
log_bin_index       = /var/log/mysql/mysql-bin.log.index
relay_log           = /var/log/mysql/mysql-relay-bin
relay_log_index     = /var/log/mysql/mysql-relay-bin.index
expire_logs_days    = 10
max_binlog_size     = 100M
log_slave_updates   = 1
auto-increment-increment = 2
auto-increment-offset = 1

server_id           = 2
log_bin             = /var/log/mysql/mysql-bin.log
log_bin_index       = /var/log/mysql/mysql-bin.log.index
relay_log           = /var/log/mysql/mysql-relay-bin
relay_log_index     = /var/log/mysql/mysql-relay-bin.index
expire_logs_days    = 10
max_binlog_size     = 100M
log_slave_updates   = 1
auto-increment-increment = 2
auto-increment-offset = 2