[转] MySQL "replace into" 的坑 (5.5 ROW格式)
MySQL 对 SQL 有很多扩展,有些用起来很方便,但有一些被误用之后会有性能问题,还会有一些意料之外的副作用,比如 REPLACE INTO。
比如有这样一张表:
1 |
|
auto 表有一个自增的 id 字段作为主键,字段 k 有 UNIQUE KEY 做唯一性约束。写入几条记录之后会是这样:
1 |
|
在 slave 节点上是和 master 一致的:
1 |
|
可以看到,写入三条记录之后,auto 表的 AUTO_INCREMENT 增长为 4,也就是说下一条不手工为 id 指定值的记录,id 字段的值会是 4。
接下来使用 REPLACE INTO 来写入一条记录:
1 |
|
可以看到 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 上出现了诡异的问题:
1 |
|
可以知道,当前表内数据 id 字段的最大值是 4,AUTO_INCREMENT 应该为 5,但在 slave 上 AUTO_INCREMENT 却并未更新,这会有什么问题呢?把这个 slave 提升为 master 之后,由于 AUTO_INCREMENT 比实际的 next id 还要小,写入新记录时就会发生 duplicate key error,每次冲突之后 AUTO_INCREMENT += 1,直到增长为 max(id) + 1 之后才能恢复正常:
1 |
|
没有预料到 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/
[转] MySQL "replace into" 的坑 (5.5 ROW格式)的更多相关文章
- MySQL "replace into" 的坑
MySQL 对 SQL 有很多扩展,有些用起来很方便,但有一些被误用之后会有性能问题,还会有一些意料之外的副作用,比如 REPLACE INTO. 比如有这样一张表: CREATE TABLE `au ...
- MySQL "replace into" 的坑以及insert相关操作
下面我们主要说一下在插入时候的几种情况: 1:insert ignore 2:replace into 3:ON DUPLICATE KEY UPDATE 关于insert ignore: 关于rep ...
- MySQL replace into 使用详解 及 注意事项
REPLACE的运行与INSERT很相似.只有一点例外,假如表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除.注意:除非表 ...
- MySQL REPLACE INTO 的使用
前段时间写游戏合服工具时出现过一个问题,源DB和目标DB角色表中主键全部都不相同,从源DB取出玩家数据再使用 replace into 写入目标DB中,结果总有几条数据插入时会导致目标DB中原有的角色 ...
- MySQL replace函数替换字符串语句的用法(mysql字符串替换)
MySQL replace函数我们经常用到,下面就为您详细介绍MySQL replace函数的用法,希望对您学习MySQL replace函数方面能有所启迪. 最近在研究CMS,在数据转换的时候需要用 ...
- 被mysql中的wait_timeout坑了
今天被mysql里的wait_timeout坑了 网上能搜到很多关于mysql中的wait_timeout相关的文章,但是大多数只是说明了他的作用,而且都说这个参数要配合那个inter ...
- MySQL replace into 说明(insert into 增强版)
MySQL replace into 说明(insert into 增强版) 在插入数据到一个表时,通常是这种情况:1. 先推断数据是否存在: 2. 假设不存在,则插入:3.假设存在,则更新. 在 S ...
- 【踩坑记录】记一次MySQL主从复制延迟的坑
最近开发中遇到的一个MySQL主从延迟的坑,记录并总结,避免再次犯同样的错误. 情景 一个活动信息需要审批,审批之后才能生效.因为之后活动要编辑,编辑后也可能触发审批,审批中展示的是编辑前的活动内容, ...
- Ubuntu 16.04 安装Mysql 5.7 踩坑小记
title:Ubuntu 16.04 安装Mysql 5.7 踩坑小记 date: 2018.02.03 安装mysql sudo apt-get install mysql-server mysql ...
随机推荐
- 网络爬虫之scrapy框架(CrawlSpider)
一.简介 CrawlSpider其实是Spider的一个子类,除了继承到Spider的特性和功能之外,还派生了其自己独有的更强大的特性和功能.其中最显著的功能就是"LinkExtractor ...
- ACM_闹钟人生(水题)
闹钟人生 Time Limit: 2000/1000ms (Java/Others) Problem Description: 已知一个时钟一开始指向0点,顺时针走了n个小时,求它最终所指向的数字(时 ...
- 网站开发综合技术 第一部分HTML 1.3.2表单
<form id="" name="" method="post/get" action="负责处理的服务端"&g ...
- SQL数据库--数据访问
数据访问: 对应命名空间:System.Data.SqlClient; SqlConnection:连接对象 SqlCommand:命令对象 SqlDataReader:读取器对象 //造连接字符串 ...
- .Net MVC之间的关系以及如何运用
.Net MVC组成部分:视图(views)模型(model)控制器(controller)以及路由(RouteConfig),视图跟模型的数据不进行直接的交互,他们是通过控制器进行视图模型之间的数据 ...
- 【Python-2.7】换行符和制表符
在Python中换行符“\n”表示接下来的内容将会换到下一行显示,制表符“\t”表示下面的内容显示时在前面留出空白,如打印如下内容: Dear: I love you forever! 上面的一段话分 ...
- 字符集编码---3 Windows BOM
Windows平台下存储Unicode格式的文件时,会在文件头插入2到3字节的文件头.这个文件头就是BOM(Byte Order Marks). 这个文件头在Unicode中,无对应符号.所以不必担心 ...
- 使用Spring框架的步骤
“好记性,不如烂笔头”.今天正式接触了Spring框架,第一次接触Spring框架感觉Spring框架简化了好多程序代码,开发效率大大提高.现在介绍使用Spring框架的步骤.(使用spring-fr ...
- 三维CNN:收集一些最近的3d卷积网络PointNet++
PointNet++是在PointNet上做出了改进,考虑了点云局部特征提取,从而更好地进行点云分类和分割. 先简要说一下PointNet: PointNet,其本质就是一种网络结构,按一定的规则输入 ...
- QT,折腾的几天-----关于 QWebEngine的使用
几天前,不,应该是更早以前,就在寻找一种以HTML5+CSS+Javascript的方式来写桌面应用的解决方案,为什么呢?因为前端那套可以随心所欲的写样式界面啊,恩.其实我只是想使用H5的一些新增功能 ...