replace 语句本质是“删+插”而非原地更新:先按主键或唯一索引删除旧记录,再插入新记录,导致自增id变化、触发器和外键级联各执行两次;必须有主键或unique索引,否则等同insert;推荐优先使用insert … on duplicate key update实现安全更新。
REPLACE 语句本质是「删+插」,不是 UPDATE
MySQL 的 REPLACE 不是原地修改,而是先根据主键或唯一索引尝试查找匹配行;如果存在,就先 DELETE 掉旧记录,再 INSERT 新记录。这意味着自增 ID 会变化、触发器会执行两次(一次 DELETE,一次 INSERT)、外键级联动作也会被触发两次。
常见误用场景:想更新某字段却用了 REPLACE,结果发现 ID 增了、历史记录断了、binlog 里多了一条删除日志。
- 必须确保表有主键或至少一个
UNIQUE索引,否则REPLACE等价于INSERT - 若不想改变自增 ID,应改用
INSERT ... ON DUPLICATE KEY UPDATE - 事务中使用
REPLACE要注意锁行为:它会对冲突的唯一索引值加 next-key lock,可能比普通 INSERT 更容易引发死锁
REPLACE INTO 语法与 INSERT 几乎一致,但语义完全不同
REPLACE INTO 支持和 INSERT INTO 相同的写法:列名列表、VALUES、SELECT 子查询等。但只要发生唯一键冲突,就会走删除再插入逻辑。
示例:
REPLACE INTO users (id, name, email) VALUES (1, 'Alice', '[email protected]');
如果 id=1 已存在,且 id 是主键,则原记录被删,新记录插入 —— 即使只改了 email,name 字段也会被覆盖为新值(不会保留旧值)。