下面我们主要说一下在插入时候的几种情况:

1:insert ignore

2:replace into

3:ON DUPLICATE KEY UPDATE

关于insert ignore:

关于replace into:

关于ON DUPLICATE KEY UPDATE :

MySQL 对 SQL 有很多扩展,有些用起来很方便,但有一些被误用之后会有性能问题,还会有一些意料之外的副作用,比如 REPLACE INTO。

比如有这样一张表:

CREATE TABLE `auto` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`k` int(10) unsigned NOT NULL,`v` varchar(100) DEFAULT NULL,`extra` varchar(200) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

auto 表有一个自增的 id 字段作为主键,字段 k 有 UNIQUE KEY 做唯一性约束。写入几条记录之后会是这样:

xupeng@diggle7:3600(dba_m) [dba] mysql> INSERT INTO auto (k, v, extra) VALUES (1, '1', 'extra 1'), (2, '2', 'extra 2'), (3, '3', 'extra 3');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0xupeng@diggle7:3600(dba_m) [dba] mysql> SHOW CREATE TABLE auto\G
*************************** 1. row ***************************Table: auto
Create Table: CREATE TABLE `auto` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`k` int(10) unsigned NOT NULL,`v` varchar(100) DEFAULT NULL,`extra` varchar(200) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
1 row in set (0.01 sec)xupeng@diggle7:3600(dba_m) [dba] mysql> SELECT * FROM auto;
+----+---+------+---------+
| id | k | v    | extra   |
+----+---+------+---------+
|  1 | 1 | 1    | extra 1 |
|  2 | 2 | 2    | extra 2 |
|  3 | 3 | 3    | extra 3 |
+----+---+------+---------+
3 rows in set (0.00 sec)

在 slave 节点上是和 master 一致的:

xupeng@diggle8:3600(dba_s) [dba] mysql> SELECT * FROM auto;
+----+---+------+---------+
| id | k | v    | extra   |
+----+---+------+---------+
|  1 | 1 | 1    | extra 1 |
|  2 | 2 | 2    | extra 2 |
|  3 | 3 | 3    | extra 3 |
+----+---+------+---------+
3 rows in set (0.00 sec)xupeng@diggle8:3600(dba_s) [dba] mysql> SHOW CREATE TABLE auto\G
*************************** 1. row ***************************Table: auto
Create Table: CREATE TABLE `auto` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`k` int(10) unsigned NOT NULL,`v` varchar(100) DEFAULT NULL,`extra` varchar(200) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

可以看到,写入三条记录之后,auto 表的 AUTO_INCREMENT 增长为 4,也就是说下一条不手工为 id 指定值的记录,id 字段的值会是 4。

接下来使用 REPLACE INTO 来写入一条记录:

xupeng@diggle7:3600(dba_m) [dba] mysql> REPLACE INTO auto (k, v) VALUES (1, '1-1');
Query OK, 2 rows affected (0.01 sec)xupeng@diggle7:3600(dba_m) [dba] mysql> SELECT * FROM auto;
+----+---+------+---------+
| id | k | v    | extra   |
+----+---+------+---------+
|  2 | 2 | 2    | extra 2 |
|  3 | 3 | 3    | extra 3 |
|  4 | 1 | 1-1  | NULL    |
+----+---+------+---------+
3 rows in set (0.00 sec)xupeng@diggle7:3600(dba_m) [dba] mysql> SHOW CREATE TABLE auto\G
*************************** 1. row ***************************Table: auto
Create Table: CREATE TABLE `auto` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`k` int(10) unsigned NOT NULL,`v` varchar(100) DEFAULT NULL,`extra` varchar(200) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

可以看到 MySQL 说 “2 rows affected”,可是明明是只写一条记录,为什么呢?这是因为 MySQL 在执行 REPLACE INTO auto (k) VALUES (1) 时首先尝试 INSERT INTO auto (k) VALUES (1),但由于已经存在一条 k=1 的记录,发生了 duplicate key error,于是 MySQL 会先删除已有的那条 k=1 即 id=1 的记录,然后重新写入一条新的记录。

这时候 slave 上出现了诡异的问题:

xupeng@diggle8:3600(dba_s) [dba] mysql> SHOW CREATE TABLE auto\G
*************************** 1. row ***************************Table: auto
Create Table: CREATE TABLE `auto` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`k` int(10) unsigned NOT NULL,`v` varchar(100) DEFAULT NULL,`extra` varchar(200) DEFAULT NULL,PRIMARY KEY (`id`),UNIQUE KEY `uk_k` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1

可以知道,当前表内数据 id 字段的最大值是 4,AUTO_INCREMENT 应该为 5,但在 slave 上 AUTO_INCREMENT 却并未更新,这会有什么问题呢?把这个 slave 提升为 master 之后,由于 AUTO_INCREMENT 比实际的 next id 还要小,写入新记录时就会发生 duplicate key error,每次冲突之后 AUTO_INCREMENT += 1,直到增长为 max(id) + 1 之后才能恢复正常:

xupeng@diggle8:3600(dba_s) [dba] mysql> REPLACE INTO auto (k, v) VALUES (4, '4');
ERROR 1062 (23000): Duplicate entry '4' for key 'PRIMARY'
xupeng@diggle8:3600(dba_s) [dba] mysql> REPLACE INTO auto (k, v) VALUES (5, '5');
Query OK, 1 row affected (0.00 sec)xupeng@diggle8:3600(dba_s) [dba] mysql> SELECT * FROM auto;
+----+---+------+---------+
| id | k | v    | extra   |
+----+---+------+---------+
|  2 | 2 | 2    | extra 2 |
|  3 | 3 | 3    | extra 3 |
|  4 | 1 | 1-1  | NULL    |
|  5 | 5 | 5    | NULL    |
+----+---+------+---------+
4 rows in set (0.00 sec)

没有预料到 MySQL 在数据冲突时实际上是删掉了旧记录,再写入新记录,这是使用 REPLACE INTO 时最大的一个误区,拿之前的例子来说,执行完 REPLACE INTO auto (k, v) VALUES (1, ‘1-1’) 之后,由于新写入记录时并未给 extra 字段指定值,原记录 extra 字段的值就「丢失」了,而通常这并非是业务上所预期的,更常见的需求实际上是,当存在 k=1 的记录时,就把 v 字段的值更新为 ‘1-1’,其他未指定的字段则保持原状,而满足这一需求的 MySQL 方言是 INSERT INTO auto (k, v) VALUES (1, ‘1-1’) ON DUPLICATE KEY UPDATE v=VALUES(v);

鉴于此,很多使用 REPLACE INTO 的场景,实际上需要的是 INSERT INTO … ON DUPLICATE KEY UPDATE,在正确理解 REPLACE INTO 行为和副作用的前提下,谨慎使用 REPLACE INTO。

参考:

https://blog.xupeng.me/2013/10/11/mysql-replace-into-trap/

https://9iphp.com/web/php/mysql-on-duplicate-key-update.html

MySQL replace into 的坑以及insert相关操作相关推荐

  1. mysql 数据表内容_mysql数据库内容相关操作

    第一:介绍 mysql数据内容的操作主要是: INSERT实现数据的插入 UPDATE实现数据的更新 DLETE实现数据的删除 SELECT实现数据的查询. 第二:增(insert) 1.插入完整的数 ...

  2. mysql在cmd命令行下的相关操作

    1.设置新的root密码. mysql -u root -p 直接回车,无需输入密码就可以进入数据库了. 此时在命令行下执行 use mysql (切换到系统数据库) 执行以下语句既可修改root用户 ...

  3. mysql replace报错_Mysql中replace与replace into的用法讲解

    Mysql replace与replace into都是经常会用到的功能:replace其实是做了一次update操作,而不是先delete再insert:而replace into其实与insert ...

  4. MySQL:讨人喜欢的 MySQL replace into 用法(insert into 的增强版)

    讨人喜欢的 MySQL replace into 用法(insert into 的增强版) 在向表中插入数据的时候,经常遇到这样的情况:1. 首先判断数据是否存在: 2. 如果不存在,则插入:3.如果 ...

  5. MariaDB/MySQL防止重复插入相同记录:INSERT IGNORE或者REPLACE

    MySQL防止重复插入相同记录有2种常用的方法. 1 使用 INSERT IGNORE 使用 INSERT IGNORE 可以在插入具有相同主键的数据时不做重复插入. mysql> SELECT ...

  6. insert 语句_替换某字段中的特定字符串——MySQL REPLACE 与INSERT 函数详解

    MySQL提供了一个非常实用的字符串函数--REPLACE() 函数,它允许用新的字符串替换字段中的特定字符串,而不再需要自己写函数去替换,用起来非常的方便. REPLACE() 函数语法 需要注意的 ...

  7. mysql insert replace_mysql 操作总结 INSERT和REPLACE

    --他人总结的 用于操作数据库的SQL一般分为两种,一种是查询语句,也就是我们所说的SELECT语句,另外一种就是更新语句,也叫做数据操作语句. 言外之意,就是对数据进行修改.在标准的SQL中有3个语 ...

  8. MySQL replace into (insert into 的增强版)

    在使用SQL语句进行数据表插入insert操作时,如果表中定义了主键,插入具有相同主键的记录会报错:  Error Code: 1062. Duplicate entry 'XXXXX' for ke ...

  9. MySQL 当记录不存在时insert,当记录存在时update(ON DUPLICATE KEY UPDATE, REPLACE语句)...

    MySQL 当记录不存在时insert,当记录存在时更新 网上基本有三种解决方法. 第一种:示例一:insert多条记录 假设有一个主键为 client_id 的 clients 表,可以使用下面的语 ...

最新文章

  1. dnf拍卖行计算机在线,DNF助手拍卖行在哪里 拍卖行物价实时查询
  2. oracle executesqlcommand,Oracle Execute Command Sql Script in Win
  3. 神策数据荣膺“2017 年度最受欢迎企业服务商 Top 10”
  4. Linux 小知识翻译 - 「单CD 的linux」
  5. scrapy-redis爬虫如何发送POST请求
  6. 安装ISA2004后,加入域时提示:远程过程调用失败且未运行的解决办法
  7. ImageLoader的简单分析(终结篇)
  8. OSSIM安装zabbix
  9. 重磅!Spring Cloud 生态再添新套件:Spring Cloud Tencent
  10. MybatisPlus学习笔记
  11. radon变换(c++、OpenCV实现)
  12. 吐槽国内各大公司的漏洞报告平台
  13. latex 两行 大括号_用laTeX排版大括号的三种方法
  14. 从事热爱的工作和积极乐观
  15. 盲盒App就是一元购吗?
  16. Linux 2.6下Driver开发的34个变化[转贴]
  17. 性能测试中怎么检测CPU情况
  18. iOS8 对开发人员来说意味着什么?
  19. 优盘格式化了怎么恢复里面的数据?
  20. 《洋妞》万像电影节揽四奖 或打造同名综艺节目

热门文章

  1. WSAAsyncSelect模型
  2. .Net转Java自学之路—Hibernate框架篇三(查询方式)
  3. 剖析一个再次调整的seo排名案例
  4. SliverLight注册字典转换器方法
  5. SH 脚本注意事项之 IF 判断
  6. 为什么要重写hashcode()方法
  7. MonolithFirst:单体应用优先策略
  8. 强制回收和IDisposable.Dispose方法
  9. SQL server2000数据库备份和还原语句
  10. ubuntu10.04 解决打开windows记事本.txt文件乱码的方法