我有一个数据库,出于备份原因我打算对其进行复制(目前性能不是问题)。
我们已经正确设置了复制并对其进行了测试,一切正常。
然后我们意识到它会将所有写入复制到临时表,这实际上意味着复制一天的数据对于空闲从属来说花费了将近两个小时。
这样做的原因是我们每 15 分钟通过 cronjob 重新计算数据库中的一些数据以确保它同步(总共需要大约 3 分钟,因此在网络请求期间执行这些操作是 Not Acceptable ;相反,我们只是存储修改而不尝试在 Web 请求中重新计算任何内容,然后批量完成所有工作)。为了有效地处理这些数据,我们使用临时表(因为存在很多相互依赖关系)。
现在,第一个问题是,如果我们在从属服务器正在处理使用该临时表的事务的过程中重新启动它,则临时表不会持久存在。这可以通过不使用临时表来避免,尽管这有其自身的问题。
更严重的问题是,如果不是所有的重新计算(它一个接一个地进行,所以每 15 分钟重建一次数据没有任何好处),从站很容易在不到半小时内 catch ...你可以从字面上看到它停留在 1115,只是为了快速 catch 并停留在 1130 等)。
我们想到的一个解决方案是将所有重新计算从复制的数据库中移出,这样从服务器就不会复制它。但它有缺点,我们必须修剪它最终更新的表,使我们的奴隶实际上“阉割”,即。在实际使用它之前,我们必须重新计算它上面的所有内容。
有没有人遇到过类似的问题和/或您会如何解决?我是否遗漏了一些明显的东西?
最佳答案
我想出了解决方案。它利用了 Nick 提到的 replicate-do-db。写在这里以防有人遇到类似问题。
在这种情况下仅使用 replicate-(wild-)do* 选项的问题(就像我说的,我们使用临时表来重新填充中央表)是您要么忽略临时表并重新填充没有数据的中央表(这会导致进一步的问题,因为所有依赖于最新的中央表的查询都会产生不同的结果)或者您忽略具有类似问题的中央表。更不用说,在将任何这些选项添加到 my.cnf 后,您必须重新启动 mysql。我们想要的东西可以涵盖所有这些案例(以及 future 的案例),而无需任何进一步的重启。
因此,我们决定将数据库拆分为“真实”数据库和“工作区”数据库。仅复制“真实”数据库(我想您可以决定用于 replicate-wild-do-table 语法的表名约定)。
所有临时表工作都在“workarea”数据库中进行,为了避免上述依赖性问题,我们不会通过 INSERT ... SELECT 或 RENAME 填充中央表(位于“真实”数据库中) TABLE,而是查询 tmp 表以在实时表上生成一种差异(即为新行生成 INSERT 语句,为旧行生成 DELETE 并在必要时更新)。
这样,唯一被复制的查询就是所需的更新,没有别的,即。一些(大多数?)每 15 分钟发生一次的重新计算查询甚至可能不会进入从属状态,而那些会进入从属状态的查询将是最少的,而且根本不会消耗大量计算资源,只是简单的 INSERT 和 DELETE。
关于mysql - 具有大量临时表写入的复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/116228/