MySQL 复制 - 复制到从属服务器上的多个数据库?

Jas*_* Mc 6 mysql replication

我在主数据库中有一个表,我想将其复制到一台从属服务器上的多个数据库。像这样:

masterDB.tableA -> slaveDB1.tableA
masterDB.tableA -> slaveDB2.tableA
Run Code Online (Sandbox Code Playgroud)

slaveDB1 和 slaveDB2 在同一个从服务器上。这可能吗?

我可以让 slaveDB1 的复制工作没有问题,但因为它忽略了 my.cnf 中用于 slaveDB2 的命令:

replicate-rewrite-db="masterDB->slaveDB1"
replicate-rewrite-db="masterDB->slaveDB2"

replicate-wild-do-table=slaveDB1.tableA%
replicate-wild-do-table=slaveDB2.tableA%
Run Code Online (Sandbox Code Playgroud)

我是否遗漏了什么,或者这不能通过 MySQL 复制来完成?

Aar*_*own 6

第一个明显的问题是你为什么要这样做?这可能是一个坏主意,完全没有必要,因为您可以跨数据库加入:

SELECT * FROM db1.table1 JOIN db2.table2 ON db1.table1_id = db2.table2_id WHERE ...
Run Code Online (Sandbox Code Playgroud)

接下来,为了理解为什么这不起作用,您首先需要了解 MySQL 复制的基础知识。总之:

  1. 在master上,执行一条语句
  2. 在 master 上,该语句被写入二进制日志
  3. 在从站上,SLAVE IO_THREAD连接到主站,从已知位置读取二进制日志,并将查询写入本地中继日志
  4. 在从站上,SLAVE SQL_THREAD读取中继日志并执行语句。

您似乎期望通过为同一数据库设置多个重写语句,SQL 线程将执行中继日志语句两次。不是这种情况。从文档中,replicate-rewrite-db只是USE db在写入中继日志时更改了 的值,因此正在评估您的一个或另一个语句,但不会同时评估两者。

为了完成您正在尝试做的事情,您会想到几个选项

  1. 在同一主机上的不同端口上运行多个 MySQL 实例。这可以通过mysqld_multi来完成。这非常简单,并且可以符合您的重写规则。
  2. 将 BLACKHOLE 存储引擎与主服务器上的 AFTER INSERT、AFTER UPDATE 和 AFTER DELETE 触发器一起使用。这非常难看,但适用于某些用例

#2 的样子是这样的:

在主服务器上,创建第二个数据库和使用 BLACKHOLE 存储引擎的表的副本:

mysql> create database db1;
Query OK, 1 row affected (0.03 sec)

mysql> create database db2;
Query OK, 1 row affected (0.00 sec)

master> use db1;
Database changed
mysql> create table foo ( id int auto_increment primary key, name varchar(32) not null ) engine=innodb; 
Query OK, 0 rows affected (0.16 sec)

mysql> use db2;
Database changed
master> create table foo ( id int auto_increment primary key, name varchar(32) not null ) engine=BLACKHOLE;
Query OK, 0 rows affected (0.05 sec)

master> use db1;
Database changed
master> CREATE TRIGGER insert_into_blackhole AFTER INSERT ON foo FOR EACH ROW INSERT INTO db2.foo SELECT * FROM db1.foo WHERE id = NEW.id;

master> CREATE TRIGGER update_into_blackhole AFTER UPDATE ON foo FOR EACH ROW UPDATE db2.foo2 SET id = NEW.id, name = NEW.name WHERE id = OLD.id;

master> CREATE TRIGGER delete_from_blackhole AFTER DELETE ON foo FOR EACH ROW DELETE FROM db2.foo2 WHERE id = OLD.id;
Run Code Online (Sandbox Code Playgroud)

在从站上,创建表作为其常规存储引擎。

对 master://db1.foo 的 INSERT/UPDATE/DELETE 操作将写入 db2.foo 的二进制日志,然后在从属设备上重放,它会在两个地方都存在。

这有很多警告,这里只是其中的几个。我建议进行广泛的测试。

  • 只有 INSERT/UPDATE/DELETE 操作才会在这两个地方重现。
  • ALTER TABLE 操作不会被复制,因此必须手动对 BLACKHOLE 和主表进行更改。
  • TRUNCATE TABLE 操作不会被复制。
  • 检测不同步的数据将非常困难。
  • 批量操作将阻塞,直到触发器完成。BLACKHOLE 非常快,因为它本质上是 /dev/null,但在足够大的批次中,简单地生成语句可能需要很长时间。如果您执行 1000 行的批量 INSERT/UPDATE/DELETE,将生成 1000 个单独的语句以针对 BLACKHOLE 表执行。您可以通过设置中继从站来改进这一点。
  • 由于从批量更新到单个行更新的转换,从站可能有滞后的趋势。

使用中继从站: 您的复制拓扑如下所示:

master -> relay -> slave
Run Code Online (Sandbox Code Playgroud)

在中继从站拓扑中,您​​最终会得到一个未更改的主站,而 BLACKHOLE 配置将位于中继从站上。包含副本的常规从站将是中继的从站。这将防止主机上的写入速度减慢。请注意,由于触发器应用于从属的方式,中继从属拓扑仅适用于基于 STATEMENT 的复制。

警告:我确定我遗漏了一些关键细节,因此请对其进行广泛的测试。

我的建议是:不要这样做。我想不出有什么好的理由说明为什么您需要在同一台服务器上的两个地方复制完全相同的数据。