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

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

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

转载于:https://www.cnblogs.com/duhuo/p/5492121.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573587.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php实现tcp连接的原理,PHP实现TCP实例

NotifyService.phpclass NotifyService extends Model{private static $client;private static $redis;/*** 初始化*/protected static function initial(){$url tcp:// . config(ctrl_service.host) . : . config(ctrl_service.port);self::$client stream_socket_client($u…

docker ps3netsrv_QNAP 威联通 NAS TS-212P应用系列 篇一:实践基于QNAP平台搭建PS3NETSRV服务...

QNAP 威联通 NAS TS-212P应用系列 篇一:实践基于QNAP平台搭建PS3NETSRV服务2015-01-01 13:44:0047点赞307收藏70评论小编注:此篇文章来自即可瓜分10万金币,周边好礼达标就有,邀新任务奖励无上限,点击查看活动详情追加修…

一周内自动登录php,利用php实现一周之内自动登录存储机制(cookie、session、localStorage)...

cookie、session、localStorage这三个应该是最让程序员头疼的了,我利用简单的登录界面的username和password来说明一下吧.1.cookie用来存储用户相关数据,存储的位置在用户本地:首先是登录界面定义:Sign me in上面的代码大家都懂吧,就是一个表单.然后就是…

HTTP知识普及系列:HTTP返回状态码

状态码1XX 信息性状态码 接受的请求正在处理  2XX 成功状态码 请求正常处理完毕  3XX 重定向状态码 需要进行附加操作以完成请求  4XX 客户端错误状态码 服务器无法处理请求  5XX 服务器端错误状态码 服务器处理请求出错2XX 相应结果表明请求被正常处理了200 OK 表示从…

来电语音播报软件下载apk_消息语音播报app下载-消息语音播报安卓版 v1.0.1 - 安下载...

消息语音播报app是一款语音播报工具,它可以将微信、QQ、短信等消息进行语音播报,让你能够第一时间知晓消息内容,无需进入界面也能知晓发来的消息;它支持多个场就下使用,开启语音播报后无需你手动打开手机查看消息&…

linux创建特殊文件rules,RHEL5 Oracle Linux 5上生成正确的udev rule 规则文件

RHEL5 Oracle Linux 5上生成正确的udev rule 规则文件1.确认在所有RAC节点上已经安装了必要的UDEV包[rootrh2 ~]# rpm -qa|grep udevudev-095-14.21.el52.通过scsi_id获取设备的块设备的唯一标识名,假设系统上已有LUN sdc-sdifor i in c d e f g h i;doecho "s…

HTTP知识普及系列:HTTP首部

HTTP协议的请求和响应报文中必定包含HTTP首部。首部内容为客户端和服务器分别处理请求和响应提供所需要的信息。在请求中,HTTP报文由方法、URI、HTTP版本、HTTP首部字段等部分构成。在响应中,HTTP报文由HTTP版本、状态码(数字和原因短语&…

maya材质sheen_maya怎样做耐磨金属质感?

maya做出金属质感的方法:基本属里就调颜色跟漫反,colour任意Diffuse调低,滑杆三分之一到四分之一左右Specular Shading高光属Ecceicity、Specular Roll Off以及Specular Color控制高光点强度。面积颜色属一般金属的话第一个打到左边四分之一到…

swift 2.2 语法 (上)

前言&#xff1a; 1.此文中的语法会根据Swift的升级变动而更新。 2.如果需要请移步 -> swift2.2 语法&#xff08;中&#xff09;、swift 2.2语法&#xff08;下&#xff09; Swift与OC中常见的区别 导入框架 OC: #import <UIKit>#import "AFNetWorking.h"…

linux系统创建操作系统用户,linux系统中用户组创建管理linux操作系统 -电脑资料...

用户组管理包括对用户组创建&#xff0c;删除&#xff0c;修改及查看组操作命令&#xff0c;下面我们一起来看看希望本文章对各位同学会有所帮助哦&#xff0c;1&#xff0c;创建组groupadd test增加一个test组2&#xff0c;修改组groupmod -n test2 test将test组的名子改成tes…

android 半透明色值_Android 色值转换成透明度色值

在日常的android开发过程中&#xff0c;UI设计师一般都会或多或少的做一些不同透明度的背景&#xff0c;从而提高交互效果。 一般这个时候设计师们都会丢给我们一个色值&#xff0c;然后告诉我们&#xff0c;透明度30%&#xff0c;40% ......。 如果我们这个时候是给一个view添…

HTML中id、name、class 区别

HTML 中 id与name 区别 一个name可以同时对应多个控件&#xff0c;比如checkbox和radio 而id必须是全文档中唯一的 id的用途 1&#xff09; id是HTML元素的Identity&#xff0c;主要是在客户端脚本里用。 2&#xff09; label与form控件的关联&#xff0c;如 <label for&quo…

Linux系统查看系统硬件,linux怎么查看系统硬件信息

有时候想查看电脑中的系统硬件信息不知道怎么办下面是学习啦小编带来的关于linux怎么查看系统硬件信息的内容&#xff0c;欢迎阅读!linux怎么查看系统硬件信息?查看cpu&#xff1a;lscpu命令&#xff0c;查看的是cpu的统计信息.blueblue-pc:~$ lscpuArchitecture: i686 #cpu架…

manchi翻译中文 mi_求这一段意大利文歌词中文翻译(Mi Manchi)

机器翻译的实在太强大了^_^&#xff01;?你给的歌词不太准确啊&#xff0c;我帮你简单的翻译了一下。由于我是意语水平有限&#xff0c;可能会有小错误&#xff0c;还请高手多指教啊。你要的歌是Fausto Leali在1988年的流行曲&#xff0c;我是在找anna oxa的1988年Quando nasc…

图片的部分拉伸

- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight: (NSInteger)topCapHeight 这个函数是UIImage的一个实例函数&#xff0c;它的功能是创建一个内容可拉伸&#xff0c;而边角不拉伸的图片&#xff0c;需要两个参数&#xff0c;第一个是左边…

linux写一个ls命令,linux 下 如何自己写 ls 命令

有过linux 基础 都知道 ls 命令的作用下面给出实现代码#include #include #include #include #include #include #include #include #include #include int fun1(char *dir,char *filename){struct stat buf;char out[100];if(stat(dir,&buf)<0){perror("stat"…

java开发 时间类型的转换

1.String转date SimpleDateFormat format new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time"2016-05-16 12:45:55"; Date date; try {   date format.parse(time);   System.out.print("Format To times:"date); } catch (Parse…

designer pyqt5 界面切换_PyQt5快速上手基础篇3-设置窗口标题和图标

前言本节我们为QT Designer生成的UI界面添加图标和窗口标题。一、实例运行1. QT Designer设计UI打开designer.exe,使用默认的Main Window创建&#xff0c;直接点击Create按钮即可设计UI图如下&#xff0c;并保存为test.ui2 将test.ui转换为ui_test.py进入ui_test.py目录&#x…

linux系统gpu test,轻量级显卡测试软件GpuTest 0.4.0版下载,支持windows Linux MAC-站长资讯中心...

说到显卡测试&#xff0c;我们一定会想到3D Mark&#xff0c;可是看着3D Mark那几百兆的大小和小水管的网速&#xff0c;有没有轻量级的测试软件呢&#xff1f;GpuTest就是一款十分小巧的软件&#xff0c;这是一款基于OpenGL的显卡压力测试软件&#xff0c;GpuTest还是一款跨平…

celery 可视化_Django中Celery的实现介绍(一)

Django中Celery的实现Celery介绍Celery是基于Python开发的一个分布式任务队列框架&#xff0c;支持使用任务队列的方式在分布的机器/进程/线程上执行任务调度。上图展示的是Celery的架构&#xff0c;它采用典型的生产者-消费者模式&#xff0c;主要由三部分组成&#xff1a;bro…