如何在主 - 主动 - 主动复制环境中处理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
...
在负载较重(很多插入)环境中,请求可以发送到两个主服务器(用于perf,高可用性,0停机模式更改原因)。
如果两个主人同时创建2个CALLERS记录(是的,可以):
在复制模式=具有ON DUPLICATE KEY UPDATE的行中,复制也会中断(因为ON DUPLICATE KEY UPDATE未应用于相对的主服务器上)
在复制模式=语句中,复制也会中断
在具有ON DUPLICATE KEY UPDATE的复制模式=语句中,复制继续工作......但我们可能会有不一致的记录:
如果两个主人同时创建2个CALLERS,
处理这个非常简单的案例的最佳解决方案是什么?
我想过像这样的解决方案,但它们有很大的缺点
在这些情况下,不要通过合并CALLERS和CALLS表来使用UNIQUE索引,但这是一个巨大的功能损失......并继续使用基于ROW的复制。但是:
不要使用AUTO_INCREMENT(不要让MySQL选择id值),但是:
答案 0 :(得分:1)
使用标准复制的多主机不提高写入性能 - 所有写入必须应用于所有主机。
带有标准复制的多主机在UNIQUE
和PRIMARY
键方面存在许多问题。这是大多数人避免写给两位大师的主要原因。
AUTO_INCREMENT
通常可以通过使用auto_increment_increment
=主数量来设置问题,auto_increment_offset
设置为不同的值(1,2,..)。这就是加莱拉在幕后所做的事情。
ROW
与STATEMENT
- 不应有任何区别。
Galera有很多优点,特别是如果你有至少3个节点。特别是因为HA是一个目标。
你有很多INSERTs
?它们是单行还是批量或LOAD DATA
?单行比任何其他行都慢得多(在任何情况下)。在所有情况下,您都必须检查错误。在某些情况下,您可能会遇到“死锁”和“回滚”,需要重播事务。
小心IGNORE
选项 - 它可以“刻录”auto_increment id。 More discussion
另见Techniques for really high speed ingestion。也许你可以在一台机器上获得足够的速度。
旁注:country_id CHAR(2)
应为CHARACTER SET ascii
;使用utf8
它将始终占用6个字节。