MySQL中 replace into是否像預期樣:若表中有已經存在的數據,則把已經存在的數據刪除,插入新數據?mysql
準備數據sql
CREATE TABLE `test_replace` ( `id` int(11) NOT NULL AUTO_INCREMENT, `str1` char(10) DEFAULT NULL, `str2` char(10) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uqx_str` (`str1`) ) ENGINE=InnoDB; insert into test_replace(id,str1,str2) values(2,1234,'aaabbbb'),(4,123456,'bbbbxxxx'); select * from test_replace; +----+--------+----------+ | id | str1 | str2 | +----+--------+----------+ | 2 | 1234 | aaabbbb | | 4 | 123456 | bbbbxxxx | +----+--------+----------+ 2 rows in set (0.00 sec)
replace into test_replace(id,str1,str2) values(2,'xxxx','yyy'); Query OK, 2 rows affected (0.00 sec) select * from test_replace; +----+--------+----------+ | id | str1 | str2 | +----+--------+----------+ | 2 | xxxx | yyy | | 4 | 123456 | bbbbxxxx | +----+--------+----------+
binlog中記錄內容
大數據
replace into test_replace(id,str1,str2) values(8,'xxxx','ppppp'); Query OK, 2 rows affected (0.01 sec) select * from test_replace; +----+--------+----------+ | id | str1 | str2 | +----+--------+----------+ | 4 | 123456 | bbbbxxxx | | 8 | xxxx | ppppp | +----+--------+----------+ show create table `test_replace`\G *************************** 1. row *************************** Table: test_replace Create Table: CREATE TABLE `test_replace` ( `id` int(11) NOT NULL AUTO_INCREMENT, `str1` char(10) DEFAULT NULL, `str2` char(10) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uqx_str` (`str1`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 ###下一次插入非衝突數據時自增主鍵爲9
binlog中記錄內容code
replace into test_replace(id,str1,str2) values(8,'123456','主鍵和惟一索引衝 突'); Query OK, 3 rows affected (0.01 sec) ####插入了這條數據後,原來的兩條數據(主鍵4,8)變成了一條(主鍵 8),數據丟失!!! select * from test_replace; +----+--------+-----------------------------+ | id | str1 | str2 | +----+--------+-----------------------------+ | 8 | 123456 | 主鍵和惟一索引衝突 | +----+--------+-----------------------------+ show create table test_replace\G *************************** 1. row *************************** Table: test_replace Create Table: CREATE TABLE `test_replace` ( `id` int(11) NOT NULL AUTO_INCREMENT, `str1` char(10) DEFAULT NULL, `str2` char(10) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uqx_str` (`str1`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 1 row in set (0.00 sec)
binlog中記錄內容blog
場景2:索引
場景3:同步
經驗證:mysql5.7 和mysql8.0均是上訴狀況table
replace into在只存在主鍵衝突時會按預期的那樣;若只有惟一索引衝突時 主從切換後致使新主庫主鍵衝突錯誤、下游大數據數據不一致問題;同時存在主鍵衝突和惟一索引衝突可能會致使丟失數據。業務上不該使用replace into,應該在代碼對惟一數據衝突做處理class