【问题标题】:How to handle unique indexes with MySQL master master replication如何使用 MySQL 主主复制处理唯一索引
【发布时间】:2016-06-26 12:49:17
【问题描述】:

在主-主主动-主动复制环境中如何处理 UNIQUE 索引?

SQL 架构示例:

CALLS
  id INTEGER PRIMARY AUTO_INCREMENT
  caller_id INTEGER + INDEX
  start_date datetime
  end_date datetime
  ...

CALLERS
  id INTEGER PRIMARY AUTO_INCREMENT
  phone VARCHAR UNIQUE
  country_id CHAR(2)
  city_id INTEGER
  ...

在重负载(大量插入)环境中,可以将请求发送到两个主服务器(出于性能、高可用性、0 停机模式更改原因)。

如果在两个主服务器上同时创建 2 个 CALLERS 记录(是的,可以):

  • 在复制模式=行中,复制因 DUPLICATE 事件而中断
  • 在复制模式=带有 ON DUPLICATE KEY UPDATE 的行中,复制也会中断(因为 ON DUPLICATE KEY UPDATE 未应用于对面的主节点)

  • 在复制模式=语句中,复制也会中断

  • 在复制模式 = 使用 ON DUPLICATE KEY UPDATE 的语句中,复制继续工作......但我们可能会有不一致的记录:

    如果在两个 master 上同时创建了 2 个 CALLERS,

    • master1.CALLERS.id=1 masters1.CALLS.caller_id = 1
    • master2.CALLERS.id=2 master2.CALLS.caller_id = 2
    • 在两个主服务器上,一旦复制,复制的 CALLS 记录将有一个 caller_id 列指向不存在的记录

处理这个非常简单的案例的最佳解决方案是什么?

我想过这样的解决方案,但它们有很大的缺点

  • 在这些情况下不要通过合并 CALLERS 和 CALLS 表来使用 UNIQUE 索引,但这是一个巨大的功能损失......并继续使用基于 ROW 的复制。但是:

    • 这不适用于所有 UNIQUE 索引情况!
  • 不要使用 AUTO_INCREMENT(不要让 MySQL 选择 id 值),但是:

    • 如何在没有 SPOF 和性能下降的情况下生成替代唯一值? (可能适合 4 字节列的内容​​)
    • 必须更改所有应用程序(真实的一百多个表)

【问题讨论】:

  • 您可以设置 AUTO_INCREMENT 以便一个 Master 仅创建偶数 Id,而其他奇数 Id。所以两个Master可以同时创建Records没有问题
  • 这绝对与问题无关....问题不在于 AUTO INC,而在于 UNIQUE 索引
  • 对不起 - 我的错误。为什么你不使用 Galera Option。所以复制是同步的。如果你使用 MariaDB 10.1x,你可以同时处理异步和 Galera 复制
  • mode=statement的不一致问题说明你没有使用事务。您正在同时更新两个表(调用者和调用),因为它们是相关的,所以它们应该在同一个事务中以避免不一致。
  • 2 条记录可以在同一个事务中,但仍然不能解决 UNIQUE indexe hell @BerndBuffen > 这有可能!同步模式会阻止双方同时创建唯一密钥

标签: mysql replication mariadb unique-index


【解决方案1】:

具有标准复制的多主服务器不会提高写入性能 - 所有写入都必须应用于所有主服务器。

具有标准复制的多主机在UNIQUEPRIMARY 键方面存在许多问题。这是大多数人避免两个大师的主要原因。

AUTO_INCREMENT 问题通常可以通过使用auto_increment_increment = master 的数量,并将auto_increment_offset 设置为不同的值 (1,2,..) 来防止。这就是 Galera 在幕后所做的。

ROWSTATEMENT -- 应该没有任何区别。

Galera 有很多优点,尤其是在您至少有 3 个节点的情况下。尤其是因为 HA 是一个目标。

你有很多INSERTs?它们是单行的,还是批处理的,还是LOAD DATA?单行比其他任何一个都慢得多(在任何情况下)。在所有情况下,您都必须检查错误。在某些情况下,您可能会遇到“死锁”和“回滚”,需要重播事务。

注意IGNORE 选项——它可以“烧掉”自动增量 ID。 More discussion.

另见Techniques for really high speed ingestion。也许您可以在单台机器上获得足够的速度。

旁注:country_id CHAR(2) 应该是CHARACTER SET asciiutf8 总是占用 6 个字节。

【讨论】:

    猜你喜欢
    • 2014-01-09
    • 1970-01-01
    • 2014-04-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多