【问题标题】:Does replicate-rewrite-db have any real world application?复制重写数据库是否有任何现实世界的应用程序?
【发布时间】:2023-03-26 17:20:01
【问题描述】:

我一直在试验两台 MySQL 服务器之间的主-主复制,但数据库名称不同,我遇到了一些绊脚石。看起来,虽然 UPDATE 可以按预期正常工作,但 INSERT 却不能。

虽然我会说这是一个错误,或者至少是我的设置有问题,但 MySQL 似乎说这是一个功能(herehere)。

如果如 MySQL 所说,它只适用于默认数据库,那么此设置如何具有实际的实际用途?

我错过了什么吗?


供参考my.cnf中的相关部分。我一直在通过在 phpMyAdmin 中进行插入和更新来测试这一点,如果这有什么不同的话。

主人

log-bin=mysql-bin
binlog_do_db=db1

奴隶

replicate-rewrite-db=db1->db2
replicate-wild-do-table=db2.table1

【问题讨论】:

  • 我提供了一个答案,但是我明天会设置一个实际环境来重新创建您的测试场景并验证您的情况。如果您还有时间,请尝试使用标准 mysql 控制台并比较 USE db1 和通用插入与在查询中指定数据库名称。您应该在那里看到不同之处。

标签: mysql replication database-replication


【解决方案1】:

Replication-rewrite-db 用法与其他复制选项相同。不仅Replication-rewrite-db 适用于默认数据库,而且这些:replicate-do-db, replicate-ignore-db, binlog-do-db and binlog-ignore-db。请参阅thisthis

有现实世界的目的,否则 MySQL 不会实现这个选项。它仅适用于默认数据库because-

这种“只检查默认数据库”行为的主要原因是 仅从陈述中很难知道它是否 应该被复制(例如,如果您使用的是多表 跨表操作的 DELETE 语句或多表 UPDATE 语句 多个数据库)。只检查默认值也更快 数据库而不是所有数据库(如果不需要)。

您还应该了解复制规则。来自here

我通过发出INSERT, DELETE and UPDATE 测试了phpmyadmin,并注意到(通过启用general_query_log)它发出INIT DB 'db_name'(为mysql_select_db() API 调用记录了'Init DB')。

例如:

Init DB sakila
1 Query INSERT INTO `sakila`.`actor_info` (`actor_id`, `first_name`, `last_name`, `film_info`) VALUES ('1235', 'abc', 'efg', NULL)

所以最终复制不应该中断,因为 phpmyadmin 通过在每次查询之前执行 USE db 来正确地做到这一点。

【讨论】:

  • 感谢 Ashwin,您是第一个质疑我的测试方式的人,您让我意识到我哪里出了问题。通过 phpmyadmin 发出 sql 命令确实有效,但 phpmyadmin 生成的 sql 命令的格式为 db1.table_name,所以这就是问题所在。我现在又进行了一些测试,结果看起来不错。
【解决方案2】:

我相信他们在文档中所指的是,它不会为您翻译特定的数据库名称,只会翻译 USE 设置的数据库。他们的意思是,如果您要执行以下操作:

USE db1;
INSERT INTO table_name (x,y,z) VALUES (1,2,3);

它应该如你所愿。

但是,如果您在查询中明确命名数据库,它不会自动为您翻译。例如

INSERT INTO db1.table_name (x,y,z) VALUES (1,2,3); 

很可能 phpMyAdmin 正在翻译您的查询以指定数据库名称以及表名。

编辑: 如果您可以完全控制整个系统中的查询创作,那么这确实具有实际用途,但您需要非常小心地在查询运行之前知道它们是什么。某些类型的 ORM 系统或中介会重写您的查询以使您明确。我不建议在生产环境中使用它,尤其是当多个团队正在编写与您的 MySQL 服务器接口的代码时。

【讨论】:

  • 所以要让它工作,你必须在每一个 sql 查询中指定数据库?这确定是温和的?如果 MySQL 知道要写入哪个数据库,那为什么复制引擎不知道呢?
  • 嗨迈克尔,虽然这可能有效,但没有对每个查询的作者身份,不能保证它一直有效。在这种情况下,它可能很快导致两个数据库出现差异。有没有办法让 MySQL 简单地将当前选择的数据库添加到复制引擎?
【解决方案3】:

我设置了有限数量的 MySQL 服务器,两个。一种是生产 (PROD),仅用于生产,另一种是开发,兼作灾难恢复 (DR) 和运行渴望查询。

为了启用灾难恢复,PROD 服务器使用复制复制到 DR,但如果不重命名,这将导致同一服务器上的两个数据库具有相同的名称。所以我所拥有的是生产:

db_application

在开发中我有两个

db_application (which is used for development)
slave_application (which is used for DR)

我没有在每个语句中使用 USE,而是使用连接字符串来指定哪个数据库是默认数据库,并且所有语句都不包含数据库名称。 (即 SELECT * FROM TABLE 而不是 SELECT * FROM DB.TABLE

这允许复制工作并在开发服务器上拥有与生产服务器同名的数据库。这适合我的需要,但我很感激其他人可能觉得这个设置不实用。这更适合完全控制 SQL 但对连接字符串的控制有限。

【讨论】:

  • 所以你在两台服务器之间运行复制但具有相同的数据库名称,即 db_application。我最终也不得不求助于这种情况。但是,我的问题是关于使用 replicate-rewrite-db 语句在不同的数据库名称之间切换。抱歉,这里没有赏金。
  • 不完全。复制是 db_application => slave_application。 DR 框上的 db_application 是开发实例,这就是我需要使用 replicate-rewrite-db 的原因(DR,像往常一样,是事后才想到的)
  • 那正是我所追求的,你的 my.cnf 设置是如何处理这个问题的?
  • 我目前无法访问服务器,但听起来您的配置很好,但正如迈克尔强调的那样,用于将数据插入数据库的 SQL 语句存在问题。我需要更新 SQL 和连接字符串,而不是更新 CNF。
  • 现在你又把我弄糊涂了 :( 据我所知,INSERT 可以处理不同的表名,你需要指定数据库名称,如“INSERT INTO db1.table_name ( x,y,z) VALUES (1,2,3); “。您的回答暗示您已经找到了另一种方法:“所有语句都不包含数据库名称”。但是您的最新评论与此相矛盾:“我需要更新 SQL”。请您为我澄清一下您的策略。
【解决方案4】:

我说这是一个根本性故障,他们将其作为针对同一问题的特色请求......这发生在二进制日志记录中......http://bugs.mysql.com/bug.php?id=65837

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 2011-05-28
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-01-15
    • 1970-01-01
    相关资源
    最近更新 更多