【发布时间】: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