2010-08-19 162 views
0

我遇到轻微问题。故事如下:从客户端到主服务器同步mysql表数据

我有一个文件存档系统(用PHP编写),运行在多个客户端(目前有23个)。在他们的系统上他们只有他们的文件。每天晚上,他们都需要“同步”到现场的主数据库(中央服务器)。我可以从中央服务器访问每个MySQL数据库,因此连接到它们是没有问题的。

我有一个连接到客户端数据库的脚本,选择从同步列='0000-00-00 00:00:00'(默认表示它没有同步)的表中的所有条目。然后,我会遍历每条记录,将其插入到中央服务器,并将客户端数据库记录上的同步时间设置为执行脚本的时间。这种方式很有效,但显然在多个查询中有很大的开销,我现在刚刚注意到了这些问题。

每个客户端每天可以生成多达2000 - 3000个奇数文档。有了这些大数字,它会花费太长时间(1秒/ 2文档)。

有没有更好的解决我的问题?最好是一个PHP脚本解决方案,因为我需要做日志来检查一切是否成功。

感谢

编辑: 我现在的流程是:

  1. 选择所有未同步数据
  2. BEGIN TRANSACTION
  3. 插入记录到中央数据库服务器
  4. 选择来自客户端的文档记录
  5. 将文档到中央数据库服务器
  6. 更新同步列在客户端
  7. 更新同步列在服务器上
  8. 提交交易

这是中央服务器上运行的脚本。 现在我想到了,我可以删除第7步并将其作为第5步的一部分,但这不会大大减少处理时间。

回答

1

我建议使用auto_increment_increment来保持所有服务器上的唯一id。然后,你需要做的只是一个SELECT * FROM blah WHERE sync = '0000-00-00 00:00:00',然后生成插入语句并执行它们。您不必处理任何冲突解决冲突的主键...

至于长查询时间,你需要看看你的数据的大小。如果每条记录都很大(几百kb +),则需要花费时间...

一个选项可能是为每个子服务器的表创建一个federated表。然后在master上执行SQL中的所有内容。 INSERT INTO master_table SELECT * FROM child_1_table WHERE sync = '0000-00-00 00:00:00' ...你可以避免把所有的数据都放到PHP中。你仍然可以运行一些检查,以确保一切顺利,并且你仍然可以登录,因为一切仍然是从PHP域执行的...

+0

这个ID不是问题。那些不需要同步。我通过其他各栏获得正确的记录。我只是使用ID将docarch_printout(关于文档的所有细节)表链接到docarch_printout_docs表(1 - 1仅包含文档)。另一个问题是我们没有永久连接到客户端。有些拨打按需ISDN线路。由于这一点,我不认为联邦表会起作用。不错的想法寿,从来不知道MySQL有这样的选择。 – Skippy 2010-08-19 11:25:05

+0

好吧,我想你可以在程序中存储联邦表的create sql。然后,当您连接到客户端时,运行创建脚本。然后在完成后放下它(所以它只在主动同步时使用连接)... – ircmaxell 2010-08-19 11:32:58

+0

正确。我非常喜欢这个想法。 Everythng似乎很棒,但是,我需要同步由id字段引用的2个表(1-1关系)。一个是细节,另一个是实际文档。简单地说,它只是一张桌子。对此有任何进一步的想法?谢谢。 – Skippy 2010-08-19 12:29:50

0

基本方法听起来不错 - 但花费0.5秒做一个操作是荒谬的过度 - 你通过网络拉动了多少数据?整个图像?你在做什么其他的事情?在同步列上是否有索引?

您可以通过在数据库上做未同步数据的输出得到一个小的好处:

1) mark all records available for sync with a transaction id in a new column 
2) extract all records flagged in first step into a flat file 
3) copy the file across the network 
4) load the data into the master DB 
5) if successful notify the origin server 
6) origin server then sets the sync time for all records flagged with that transaction id 

这将需要3个脚本 - 在源服务器上2(一个准备和发送数据,一个标记为完成),另一个在复制服务器上轮询数据并通知结果。

但是,如果您只是复制有关图像(而不是图像本身)的元数据,这可能不会大大侵入性能,看起来很荒谬。

C.

+0

用脚本逐步更新了我的初始文章,这样您就可以看到我的逻辑 – Skippy 2010-08-19 14:15:41

+0

这仍然不能解释为什么每个记录需要0.5秒。由于事务不能跨越2个独立的数据库管理系统,因此它不会在此处添加任何值。记录有多大? – symcbean 2010-08-19 21:18:18

+0

这是因为客户端通过ADSL(通过ISDN的几个)连接到我们。记录文件只有几千字节的文字。 – Skippy 2010-08-20 05:53:30

0

我知道你喜欢一个基于PHP的解决方案,但你可能想看看微软同步框架 -

http://msdn.microsoft.com/en-in/sync/default(en-us).aspx

这将需要被写入同步模块。但在同步逻辑和异常处理(网络故障,同步冲突等)方面存在巨大的优势,这将缩短您的时间。

只要存在.net的数据库连接器,框架也会处理非sql服务器数据库。 Mysql的应该很容易支持 - 只取一个样品从以下链接 -

http://code.msdn.microsoft.com/sync/Release/ProjectReleases.aspx?ReleaseId=4835

和适应同到MySQL。

+0

这会很棒,但它必须在CentOS上运行。我们没有任何微软服务器 – Skippy 2010-08-20 05:47:32

+0

嗯..这是一个问题好吧..虽然它会很便宜,实际上只有一个人跑这个目的!我们实际上节省了大量的开发工作,所以您可以进行一些成本/收益分析并做出决定。 – 2010-08-20 06:05:07

0

即使世界,如果你不能使用同步框架另一种可能性 -

是否有可能为你全天分配负载,而不是一天的结束?假设每次有10个新文档进入或10次编辑完成时触发同步? (如果同步是从客户端发起的话,这可以完成)。

如果您希望将同步逻辑应用到服务器端,则无论客户端何时需要同步,都可以考虑使用消息传递队列将通知从客户端发送到服务器。服务器然后可以提取数据。您可以使用内部服务总线或像azure appfabric/Amazon SQS这样的按需平台。

+0

存档归档的文档由其他应用程序在当天结束时生成。文件存档系统监视目录中的新文件,处理它等。因此,导入也是批量完成的。同步需要在一天结束时完成,以配合具有ISDN线路的客户端连接到我们用于其他目的。 – Skippy 2010-08-20 08:23:20

+0

好的..因为你已经有了一个可行的答案..干杯! – 2010-08-20 09:04:29

相关问题