how do you handle UNIQUE indexes in a master-master active-active replication environment?
SQL schema example:
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
...
In a heavy loaded (lot of inserts) environment, requests can be sent to both master (for perf, high availability, 0 downtime schema changes reasons).
if 2 CALLERS records are created at the same time (yes it can) on both masters:
- In a replication mode=row the replication breaks with a DUPLICATE event
In a replication mode=row with a ON DUPLICATE KEY UPDATE the replication breaks too (since the ON DUPLICATE KEY UPDATE is not applied on the opposite master)
In a replication mode=statement the replication breaks too
In a replication mode=statement with ON DUPLICATE KEY UPDATE the replication keep working... but we can have inconsistent records:
if 2 CALLERS are created at the same time on both masters,
- master1.CALLERS.id=1 masters1.CALLS.caller_id = 1
- master2.CALLERS.id=2 master2.CALLS.caller_id = 2
- on both master, once replicated, the replicated CALLS records will have a caller_id columns pointing on a non-existent records
What are the best solutions to handle this really simple case?
I thought to solutions like this, but they have big drawbacks
don't use UNIQUE indexe in these cases by merging CALLERS and CALLS table, but this is a huge functional loss... and keep using ROW based replication. but:
- this is not applicable to all UNIQUE indexes cases!
don't use AUTO_INCREMENT (don't let MySQL choose the id values), but:
- how will you generate alternative unique values without SPOF and without performances degradations? (something that could fit in a 4 Bytes column)
- have to change all the application (more than hundred tables in the real one)