現象:
MySQL 主從切換後,新的master上寫入數據報主鍵衝突.錯誤如下:
ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY'
原因:
主從切換後只有一張表有問題,其它的表都正常。
由於使用了replace into 方式插入導致新插入數據,導致slave上表的AUTO_INCREMENT小於Master。
在slave切換爲master後,新插入的數據導致主鍵衝突。
故障重現:
1.創建表t(id 列自增,a列爲唯一索引)
mysql> CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT '0',
`b` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `a` (`a`))
ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)
2.插入三條數據
mysql> insert into t (a,b)values(1,1),(2,2),(3,3);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
3.查看t表中的數據
mysql> select * from t;
+----+------+------+
| id | a | b |
+----+------+------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
+----+------+------+
3 rows in set (0.00 sec)
4.用replace插入兩條新數據
mysql> replace into t (a,b)values(3,30);
Query OK, 2 rows affected (0.01 sec)
mysql> replace into t (a,b)values(3,300);
Query OK, 2 rows affected (0.01 sec)
mysql> select * from t;
+----+------+------+
| id | a | b |
+----+------+------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 5 | 3 | 300 |
+----+------+------+
3 rows in set (0.00 sec)
mysql> show create table t\G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT '0',
`b` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
此時master上t表的AUTO_INCREMENT值爲6。
假設數據已經同步到slave後,發生主從切換,會出現什麼情況?
a.先檢查新master上的數據是否已經同步過來
mysql> select * from t;
+----+------+------+
| id | a | b |
+----+------+------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 5 | 3 | 300 |
+----+------+------+
3 rows in set (0.00 sec)
b.查看t表的表結構,發現AUTO_INCREMENT值爲4.與master不一致。
mysql> show create table t \G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT '0',
`b` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
c.replace into 插入值
mysql> replace into t (a,b)values(8,8);
Query OK, 1 row affected (0.00 sec)
d.出現主鍵衝突
mysql> replace into t (a,b)values(9,9);
ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY'
f.重試插入
mysql> replace into t (a,b)values(9,9);
Query OK, 1 row affected (0.01 sec)
mysql> show create table t \G
*************************** 1. row ***************************
Table: t
Create Table: CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT '0',
`b` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `a` (`a`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> select * from t;
+----+------+------+
| id | a | b |
+----+------+------+
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 4 | 8 | 8 |
| 5 | 3 | 300 |
| 6 | 9 | 9 |
+----+------+------+
5 rows in set (0.00 sec)
建議用ON DUPLICATE KEY UPDATE 的方式替換replace into。