具有大量临时表写入的复制

时间:2020-03-06 14:33:08  来源:igfitidea点击:

我有一个出于备份原因要复制的数据库(当前性能不成问题)。

我们已经正确设置了复制并对其进行了测试,一切都很好。

然后我们意识到,它会将所有写操作都复制到临时表,这实际上意味着空闲的从属服务器要复制一天的数据价值将近两个小时。

这样做的原因是,我们每隔15分钟通过cronjob重新计算数据库中的某些数据,以确保其同步(总共需要3分钟左右的时间,因此在Web请求期间执行这些操作是不可接受的;相反,我们只是存储修改内容,而不会在Web请求中尝试重新计算任何内容,然后批量进行所有工作)。为了有效地处理该数据,我们使用临时表(因为存在许多相互依赖性)。

现在,第一个问题是,如果我们在处理使用该临时表的事务的过程中重新启动从属服务器时,临时表不会持久存在。可以通过不使用临时表来避免这种情况,尽管这有其自身的问题。

更严重的问题是,如果不进行所有重新计算,从站可能会在不到半小时的时间内赶上来(它一次又一次地执行,因此每15分钟重建一次数据没有任何好处...并且从字面上我们可以看到它卡在例如1115处,只是很快就赶上并卡在1130等处)。

我们想到的一种解决方案是将所有重新计算移出复制的db,以便从属服务器不复制它。但是它的缺点是我们必须修剪它最终更新的表,从而使我们的从属设备实际上是" castrated"的。我们必须重新计算它上的所有内容,然后才能实际使用它。

有没有人遇到过类似的问题和/或者我们将如何解决?我缺少明显的东西吗?

解决方案

我相信从5.0版本开始,在MySQL中,我们可以使用表通配符来复制特定的表。可以设置许多命令行选项,但是我们也可以通过MySQL配置文件进行设置。

[mysqld]
replicate-do-db    = db1
replicate-do-table = db2.mytbl2
replicate-wild-do-table= database_name.%
replicate-wild-do-table= another_db.%

想法是我们告诉它不要复制我们指定的表以外的任何表。

我已经提出了解决方案。它利用了Nick提到的copy-do-db。如果有人遇到类似问题,请在此处写下。

在这种情况下,仅使用replicate-(wild-)do *选项的问题(如我所说,我们使用临时表重新填充中央表)是或者忽略临时表,然后不使用数据重新填充中央表(这会导致进一步的问题,因为所有依赖中心表的查询都是最新的,将产生不同的结果),或者我们忽略了中心表,这也有类似的问题。更不用说,我们必须在将所有这些选项添加到my.cnf之后重新启动mysql。我们想要一种可以覆盖所有这些情况(以及将来的情况)的东西,而无需任何进一步的重新启动。

因此,我们决定要做的是将数据库分为"实际"和"工作区"数据库。仅复制"真实"数据库(我猜我们可以决定要使用表名称的惯例来使用表行复制语法)。

所有临时表工作都在" workarea"数据库中进行,为避免上述依赖性问题,我们不会通过INSERT ... SELECT或者RENAME TABLE填充中央表(位于"实际"数据库中)。而是查询tmp表以在实时表上生成某种差异(即,为新行生成INSERT语句,为旧行生成DELETE并在必要时进行更新)。

这样,唯一复制的查询就是所需的更新,即没有其他更新。每十五分钟暂停一次的某些(大多数?)重新计算查询甚至可能不会成为从属查询,而那些查询将是最小的,并且在计算上根本不会昂贵,只需简单的INSERT和DELETE。